Customizing TinyMCE Styles Dropdown programatically

August 11, 2017

I have recently received a question from one of the developers on how to provide a different set of TinyMCE Styles in a multi site environment.

The expected result was to be able to change both the applied styles in the html editor and the dropdown that is used to choose a particular style.

There is a great post by Arve Systad about Setting editor stylesheets programmatically that is a great starting point for our problem.

We would create an EditorDescriptor where we would place the logic that returns different stylesheets per site.

using System;
using System.Collections.Generic;
using System.Linq;
using EPiServer.Cms.Shell.UI.ObjectEditing.EditorDescriptors;
using EPiServer.Core;
using EPiServer.Editor.TinyMCE;
using EPiServer.Shell.ObjectEditing;
using EPiServer.Shell.ObjectEditing.EditorDescriptors;
using EPiServer.Web;
using EPiServer.Web.Hosting;

namespace AlloyTemplates.Business.EditorDescriptors
{
    [EditorDescriptorRegistration(TargetType = typeof(XhtmlString), EditorDescriptorBehavior = EditorDescriptorBehavior.OverrideDefault)]
    public class MyEditorDescriptor : XhtmlStringEditorDescriptor
    {
        public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
        {
            base.ModifyMetadata(metadata, attributes);

            var tinyMceSettings = metadata.EditorConfiguration.FirstOrDefault(x => x.Key == "settings");
            var dictionary = tinyMceSettings.Value as Dictionary<string, object>;
            if (dictionary == null) return;

            var formatter = new TinyMCEStyleFormatter();

            var staticCssEditorCss = SiteDefinition.Current.Name.Equals("Foo") ? "/Static/css/editor.css" : "/Static/css/editor2.css";

            dictionary["content_css"] = staticCssEditorCss;
            using (var stream = GenericHostingEnvironment.VirtualPathProvider.GetFile(staticCssEditorCss).Open())
            {
                var styleFormats = formatter.CreateStyleFormats(stream);
                dictionary["style_formats"] = styleFormats;
            }
        }
    }
}

content_css property is responsible for styling the editor whereas style_formats is responsible for populating the styles dropdown.

Let's imagine we have two separate stylesheets:

  • editor1 - which should be used in the "Foo" site
h2 {EditMenuName:Header 2;color:red;}
h3 {EditMenuName:Header 3;}

h2 {
    color:red;
}
  • editor2 - which should be used in all other sites
h2 {EditMenuName:Alternative Header 2;color:blue;}
h3 {EditMenuName:Alternative Header 3;}
h4 {EditMenuName:Alternative Header 4;}

h2 {
    color:blue;
}

The end result would look as following:

tinymce_site1.png

and

tinymce_site2.png