<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><language>en</language><title>Blog posts by Jon Sexton</title> <link>https://world.optimizely.com/blogs/jon-sexton/</link><description></description><ttl>60</ttl><generator>Optimizely World</generator><item> <title>More on custom Style Formats in TinyMCE</title>            <link>https://world.optimizely.com/blogs/jon-sexton/dates/2021/6/more-on-custom-style-formats-in-tinymce/</link>            <description>&lt;p&gt;One of the problems we come across, when adding in our custom style formats for TinyMCE in the EPiServer CMS, is that this overrides the default settings.&amp;nbsp; For example, a client may require the following style format options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Headings
&lt;ul&gt;
&lt;li&gt;Heading 1&lt;/li&gt;
&lt;li&gt;Heading 2&lt;/li&gt;
&lt;li&gt;etc...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Inline
&lt;ul&gt;
&lt;li&gt;Bold&lt;/li&gt;
&lt;li&gt;Italic&lt;/li&gt;
&lt;li&gt;Underline&lt;/li&gt;
&lt;li&gt;Strikethrough&lt;/li&gt;
&lt;li&gt;Superscript&lt;/li&gt;
&lt;li&gt;Subscript&lt;/li&gt;
&lt;li&gt;Code&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Blocks
&lt;ul&gt;
&lt;li&gt;Paragraph&lt;/li&gt;
&lt;li&gt;Blockquote&lt;/li&gt;
&lt;li&gt;Div&lt;/li&gt;
&lt;li&gt;Pre&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Alignment
&lt;ul&gt;
&lt;li&gt;Left&lt;/li&gt;
&lt;li&gt;Center&lt;/li&gt;
&lt;li&gt;Right&lt;/li&gt;
&lt;li&gt;Justify&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;[a new font to select from]&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All standard, out-of-the-box stuff, for TinyMCE, however, when we add a custom style format (in this case for the new font option the client requires) in our TinyMCE intialisation class, and as described in a previous post: &lt;a href=&quot;/blogs/jon-sexton/dates/2021/2/how-to-set-primary-default-and-secondary-optional-fonts-for-tinymce-in-episerver-cms-11/,&quot;&gt;https://world.episerver.com/blogs/jon-sexton/dates/2021/2/how-to-set-primary-default-and-secondary-optional-fonts-for-tinymce-in-episerver-cms-11/,&lt;/a&gt; all these default style formatting options are blasted away, great!&lt;/p&gt;
&lt;p&gt;This blog will show how to put them back in.&lt;/p&gt;
&lt;p&gt;Firstly, there appears to be no functionality available to us to simply append a new style format option to the existing set of default options, well, none that I could find nor get working.&amp;nbsp; Unfortunately we&#39;re going to have to add these in manually; here&#39;s how...&lt;/p&gt;
&lt;p&gt;In our TinyMCE initialisation class let&#39;s start by adding in the Headings and Headings sub-menu:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;        public void ConfigureContainer(ServiceConfigurationContext context)
        {
            context.Services.Configure&amp;lt;TinyMceConfiguration&amp;gt;(config =&amp;gt;
            {
                config.Default()
                    .AddEpiserverSupport()
                    .AddSetting(&quot;paste_as_text&quot;, true)
                    .AddSetting(&quot;paste_webkit_styles&quot;, &quot;none&quot;)
                    .AddSetting(&quot;paste_merge_formats&quot;, true)
                    .AddSetting(&quot;paste_remove_styles_if_webkit&quot;, true)
                    .AddPlugin(
                        &quot;epi-link epi-dnd-processor epi-personalized-content help image fullscreen lists searchreplace hr table paste media code&quot;)
                    .Toolbar(
                        &quot;bold italic superscript subscript quote citation bullist numlist undo redo | styleselect formatselect removeformat&quot;,
                        &quot;epi-link epi-unlink anchor | cut copy paste pastetext pasteword | table | code | image epi-image-editor | epi-personalized-content | fullscreen &quot;)
                    .ContentCss(&quot;/ClientResources/Styles/editorStyles.css&quot;)
                    .BodyClass(&quot;solomon&quot;)
                    .StyleFormats(
                        // Headings
                        new
                        {
                            title = &quot;Headings&quot;, items = new[]
                            {
                                new { title = &quot;Heading 1&quot;, block = &quot;h1&quot; },
                                new { title = &quot;Heading 2&quot;, block = &quot;h2&quot; },
                                new { title = &quot;Heading 3&quot;, block = &quot;h3&quot; },
                                new { title = &quot;Heading 4&quot;, block = &quot;h4&quot; },
                                new { title = &quot;Heading 5&quot;, block = &quot;h5&quot; },
                                new { title = &quot;Heading 6&quot;, block = &quot;h6&quot; }
                            }
                        })
                    .BlockFormats(
                        &quot;Paragraph=p;Header 1=h1;Header 2=h2;Header 3=h3;Header 4=h4;Header 5=h5;Header 6=h6;&quot;);
            });
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pretty easy really and we only need to remember that each sub-item in an item we create, &quot;Headings&quot; in this case, needs to have the &lt;span style=&quot;text-decoration:&amp;#32;underline;&quot;&gt;same format as the other sub-items in the set&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Now we need to add the &#39;Inline&#39; options:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;                    .StyleFormats(
                        // Headings
                        new
                        {
                            title = &quot;Headings&quot;, items = new[]
                            {
                                new { title = &quot;Heading 1&quot;, block = &quot;h1&quot; },
                                new { title = &quot;Heading 2&quot;, block = &quot;h2&quot; },
                                new { title = &quot;Heading 3&quot;, block = &quot;h3&quot; },
                                new { title = &quot;Heading 4&quot;, block = &quot;h4&quot; },
                                new { title = &quot;Heading 5&quot;, block = &quot;h5&quot; },
                                new { title = &quot;Heading 6&quot;, block = &quot;h6&quot; }
                            }
                        },
                        // Inline (formats selected text)
                        new
                        {
                            title = &quot;Inline&quot;, items = new[]
                            {
                                new { title = &quot;Bold&quot;, inline = &quot;span&quot;, classes = &quot;boldText&quot; },
                                new { title = &quot;Italic&quot;, inline = &quot;span&quot;, classes = &quot;italicText&quot; },
                                new { title = &quot;Underline&quot;, inline = &quot;span&quot;, classes = &quot;underlineText&quot; },
                                new { title = &quot;Strikethough&quot;, inline = &quot;span&quot;, classes = &quot;strikethrough&quot; },
                                new { title = &quot;Superscript&quot;, inline = &quot;span&quot;, classes = &quot;superscript&quot; },
                                new { title = &quot;Subscript&quot;, inline = &quot;span&quot;, classes = &quot;subscript&quot; },
                                new { title = &quot;Code&quot;, inline = &quot;span&quot;, classes = &quot;code&quot; }
                            }
                        })
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The trick with these format options lies in using the &#39;inline = &quot;span&quot;&#39; and &#39;classes = &quot;[CSS CLASSNAME]&quot;&#39; attributes.&amp;nbsp; This ensures that only the selected text is formatted as required, not the entire block of text the cursor is on.&amp;nbsp; By defining a CSS classname (more on this later) we can have more than one style element, e.g. the &quot;superscript&#39; CSS class contains &#39;vertical-align: super; font-size: smaller&#39; in order to mimic the HTML &amp;lt;sup&amp;gt; tag.&lt;/p&gt;
&lt;p&gt;Now let&#39;s add in our &#39;Blocks&#39; options:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;                    .StyleFormats(
                        // Headings
                        new
                        {
                            title = &quot;Headings&quot;, items = new[]
                            {
                                new { title = &quot;Heading 1&quot;, block = &quot;h1&quot; },
                                new { title = &quot;Heading 2&quot;, block = &quot;h2&quot; },
                                new { title = &quot;Heading 3&quot;, block = &quot;h3&quot; },
                                new { title = &quot;Heading 4&quot;, block = &quot;h4&quot; },
                                new { title = &quot;Heading 5&quot;, block = &quot;h5&quot; },
                                new { title = &quot;Heading 6&quot;, block = &quot;h6&quot; }
                            }
                        },
                        // Inline (formats selected text)
                        new
                        {
                            title = &quot;Inline&quot;, items = new[]
                            {
                                new { title = &quot;Bold&quot;, inline = &quot;span&quot;, classes = &quot;boldText&quot; },
                                new { title = &quot;Italic&quot;, inline = &quot;span&quot;, classes = &quot;italicText&quot; },
                                new { title = &quot;Underline&quot;, inline = &quot;span&quot;, classes = &quot;underlineText&quot; },
                                new { title = &quot;Strikethough&quot;, inline = &quot;span&quot;, classes = &quot;strikethrough&quot; },
                                new { title = &quot;Superscript&quot;, inline = &quot;span&quot;, classes = &quot;superscript&quot; },
                                new { title = &quot;Subscript&quot;, inline = &quot;span&quot;, classes = &quot;subscript&quot; },
                                new { title = &quot;Code&quot;, inline = &quot;span&quot;, classes = &quot;code&quot; }
                            }
                        },
                        // Blocks (applies HTML tags)
                        new
                        {
                            title = &quot;Blocks&quot;, items = new[]
                            {
                                new { title = &quot;Paragraph&quot;, block = &quot;p&quot; },
                                new { title = &quot;Blockquote&quot;, block = &quot;blockquote&quot; },
                                new { title = &quot;Div&quot;, block = &quot;div&quot; },
                                new { title = &quot;Pre&quot;, block = &quot;pre&quot; }
                            }
                        })
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The difference here is that we&#39;re applying HTML tags around the block of text in scope, for &amp;lt;p&amp;gt;, &amp;lt;blockquote&amp;gt;, &amp;lt;div&amp;gt; and &amp;lt;pre&amp;gt; respectively.&lt;/p&gt;
&lt;p&gt;Now let&#39;s add in our &#39;Alignments&#39; section:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;                    .StyleFormats(
                        // Headings
                        new
                        {
                            title = &quot;Headings&quot;, items = new[]
                            {
                                new { title = &quot;Heading 1&quot;, block = &quot;h1&quot; },
                                new { title = &quot;Heading 2&quot;, block = &quot;h2&quot; },
                                new { title = &quot;Heading 3&quot;, block = &quot;h3&quot; },
                                new { title = &quot;Heading 4&quot;, block = &quot;h4&quot; },
                                new { title = &quot;Heading 5&quot;, block = &quot;h5&quot; },
                                new { title = &quot;Heading 6&quot;, block = &quot;h6&quot; }
                            }
                        },
                        // Inline (formats selected text)
                        new
                        {
                            title = &quot;Inline&quot;, items = new[]
                            {
                                new { title = &quot;Bold&quot;, inline = &quot;span&quot;, classes = &quot;boldText&quot; },
                                new { title = &quot;Italic&quot;, inline = &quot;span&quot;, classes = &quot;italicText&quot; },
                                new { title = &quot;Underline&quot;, inline = &quot;span&quot;, classes = &quot;underlineText&quot; },
                                new { title = &quot;Strikethough&quot;, inline = &quot;span&quot;, classes = &quot;strikethrough&quot; },
                                new { title = &quot;Superscript&quot;, inline = &quot;span&quot;, classes = &quot;superscript&quot; },
                                new { title = &quot;Subscript&quot;, inline = &quot;span&quot;, classes = &quot;subscript&quot; },
                                new { title = &quot;Code&quot;, inline = &quot;span&quot;, classes = &quot;code&quot; }
                            }
                        },
                        // Blocks (applies HTML tags)
                        new
                        {
                            title = &quot;Blocks&quot;, items = new[]
                            {
                                new { title = &quot;Paragraph&quot;, block = &quot;p&quot; },
                                new { title = &quot;Blockquote&quot;, block = &quot;blockquote&quot; },
                                new { title = &quot;Div&quot;, block = &quot;div&quot; },
                                new { title = &quot;Pre&quot;, block = &quot;pre&quot; }
                            }
                        },
                        // Text alignment (applies to all block formats)
                        new
                        {
                            title = &quot;Alignment&quot;, items = new[]
                            {
                                new { title = &quot;Left&quot;, selector = &quot;p,h1,h2,h3,h4,h5,h6&quot;, classes = &quot;leftAlign&quot; },
                                new { title = &quot;Center&quot;, selector = &quot;p,h1,h2,h3,h4,h5,h6&quot;, classes = &quot;centerAlign&quot; },
                                new { title = &quot;Right&quot;, selector = &quot;p,h1,h2,h3,h4,h5,h6&quot;, classes = &quot;rightAlign&quot; },
                                new { title = &quot;Justify&quot;, selector = &quot;p,h1,h2,h3,h4,h5,h6&quot;, classes = &quot;justifyAlign&quot; }
                            }
                        })
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that we&#39;ve ensured that the options are applied to all block formats.&lt;/p&gt;
&lt;p&gt;Now we can add in our new custom item, in this case a specific font:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;                    .StyleFormats(
                        // Headings
                        new
                        {
                            title = &quot;Headings&quot;, items = new[]
                            {
                                new { title = &quot;Heading 1&quot;, block = &quot;h1&quot; },
                                new { title = &quot;Heading 2&quot;, block = &quot;h2&quot; },
                                new { title = &quot;Heading 3&quot;, block = &quot;h3&quot; },
                                new { title = &quot;Heading 4&quot;, block = &quot;h4&quot; },
                                new { title = &quot;Heading 5&quot;, block = &quot;h5&quot; },
                                new { title = &quot;Heading 6&quot;, block = &quot;h6&quot; }
                            }
                        },
                        // Inline (formats selected text)
                        new
                        {
                            title = &quot;Inline&quot;, items = new[]
                            {
                                new { title = &quot;Bold&quot;, inline = &quot;span&quot;, classes = &quot;boldText&quot; },
                                new { title = &quot;Italic&quot;, inline = &quot;span&quot;, classes = &quot;italicText&quot; },
                                new { title = &quot;Underline&quot;, inline = &quot;span&quot;, classes = &quot;underlineText&quot; },
                                new { title = &quot;Strikethough&quot;, inline = &quot;span&quot;, classes = &quot;strikethrough&quot; },
                                new { title = &quot;Superscript&quot;, inline = &quot;span&quot;, classes = &quot;superscript&quot; },
                                new { title = &quot;Subscript&quot;, inline = &quot;span&quot;, classes = &quot;subscript&quot; },
                                new { title = &quot;Code&quot;, inline = &quot;span&quot;, classes = &quot;code&quot; }
                            }
                        },
                        // Blocks (applies HTML tags)
                        new
                        {
                            title = &quot;Blocks&quot;, items = new[]
                            {
                                new { title = &quot;Paragraph&quot;, block = &quot;p&quot; },
                                new { title = &quot;Blockquote&quot;, block = &quot;blockquote&quot; },
                                new { title = &quot;Div&quot;, block = &quot;div&quot; },
                                new { title = &quot;Pre&quot;, block = &quot;pre&quot; }
                            }
                        },
                        // Text alignment (applies to all block formats)
                        new
                        {
                            title = &quot;Alignment&quot;, items = new[]
                            {
                                new { title = &quot;Left&quot;, selector = &quot;p,h1,h2,h3,h4,h5,h6&quot;, classes = &quot;leftAlign&quot; },
                                new { title = &quot;Center&quot;, selector = &quot;p,h1,h2,h3,h4,h5,h6&quot;, classes = &quot;centerAlign&quot; },
                                new { title = &quot;Right&quot;, selector = &quot;p,h1,h2,h3,h4,h5,h6&quot;, classes = &quot;rightAlign&quot; },
                                new { title = &quot;Justify&quot;, selector = &quot;p,h1,h2,h3,h4,h5,h6&quot;, classes = &quot;justifyAlign&quot; }
                            }
                        },
                        // BornReady font (applies to all block formats)
                        new
                        {
                            title = &quot;BornReady font&quot;, selector = &quot;p,h1,h2,h3,h4,h5,h6&quot;, classes = &quot;bornready&quot;
                        })&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that&#39;s it for ensuring that our default options are still available even thouigh we&#39;ve added in a new style format (for the specific font).&lt;/p&gt;
&lt;p&gt;Finally, a quick look at the CSS where we&#39;ve defined our classes:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code&gt;@font-face {
    font-family: BornReady;
    font-style: normal;
    font-weight: 400;
    font-stretch: normal;
    src: url(/assets/main/fonts/bornreadyupright/normal_normal_normal.woff2) format(&quot;woff2&quot;), 
         url(/assets/main/fonts/bornreadyupright/normal_normal_normal.woff) format(&quot;woff&quot;)
}

.bornready {
    font-family: BornReady,sans-serif,Arial,Verdana,&quot;Trebuchet MS&quot;;
}
.solomon {
    font-family: Solomon,sans-serif,Arial,Verdana,&quot;Trebuchet MS&quot;;
}
.boldText {
    font-weight: bold;
}
.italicText {
    font-style: italic;
}
.underlineText {
    text-decoration: underline
}
.strikethrough {
    text-decoration: line-through;
}
.superscript {
    vertical-align: super;
    font-size: smaller;
}
.subscript {
    vertical-align: sub;
    font-size: smaller;
}
.code {
    font-family: monospace;
}
.leftAlign {
    text-align: left;
}
.centerAlign {
    text-align: center;
}
.rightAlign {
    text-align: right;
}
.justifyAlign {
    text-align: justify;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes, it would be so much easier if we had the facility to copy our default style format options, then append our new one to them.&amp;nbsp; Unfortunately we don&#39;t have that option so I hope what I have written will be useful to you all, when presented with the same scenario.&lt;/p&gt;
&lt;p&gt;Comments and thoughts always welcomed.&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/jon-sexton/dates/2021/6/more-on-custom-style-formats-in-tinymce/</guid>            <pubDate>Wed, 09 Jun 2021 15:58:01 GMT</pubDate>           <category>Blog post</category></item><item> <title>How to easily remove the extra DIV tags for Content Areas</title>            <link>https://world.optimizely.com/blogs/jon-sexton/dates/2021/6/how-to-easily-remove-the-extra-div-tags-for-content-areas/</link>            <description>&lt;p&gt;&lt;strong&gt;Extra DIV tags around Content Areas&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;From time to time we&#39;ve all had issues with the extra DIV tags EPiServer generates around Content Area items, namely blocks.&amp;nbsp; Depending upon the required output this &#39;feature&#39; (that is actually there for on-page editing in the CMS) may cause some extra padding around the output of the blocks in the Content Area, meaning that the output does not match the UX design.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;@Html.PropertyFor(x =&amp;gt; x.SomeContentArea)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which results in:&lt;/p&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;          &amp;lt;!-- Contant Area wrapper --&amp;gt;
    &amp;lt;div...&amp;gt;    &amp;lt;!-- Block element --&amp;gt;
        &amp;lt;... /&amp;gt;  &amp;lt;!-- Content of block --&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Without writing specific renderers for our Content Areas we ask, &#39;is there a way we can easily disable these extra DIV tags?&#39;.&lt;/p&gt;
&lt;p&gt;Well, EPiServer does provide us with an &#39;additionalViewData&#39; attribute called, &#39;HasContainer&#39;, which can be used, hence:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;@Html.PropertyFor(x =&amp;gt; x.SomeContentArea, new { HasContainer = false } )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Will result in:&lt;/p&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;&amp;lt;div...&amp;gt;    &amp;lt;!-- Block element --&amp;gt;
    &amp;lt;... /&amp;gt;  &amp;lt;!-- Content of block --&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Great but there&#39;s still a wrapper around the content of the block, how do we get rid of that?&lt;/p&gt;
&lt;p&gt;Well, there&#39;s a NuGet package that we can add into our solution, &#39;&lt;strong&gt;EPiBootstrapArea&lt;/strong&gt;&#39;, written by &lt;strong&gt;Valdis Iljuconoks&lt;/strong&gt;.&amp;nbsp; From version 3.3.4 onwards we can add:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;@Html.PropertyFor(x =&amp;gt; x.SomeContentArea, new { HasContainer = false, HasItemContainer = false } )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which gives us:&lt;/p&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;&amp;lt;... /&amp;gt;  &amp;lt;!-- Content of block --&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perfect!&amp;nbsp; Everything renders correctly now, AND we still have an on-page editing experience in the CMS.&lt;/p&gt;
&lt;p&gt;A word of warninng though; if we&#39;re going to render our blocks in our Content Area in the &lt;strong&gt;&amp;lt;HEAD&amp;gt;&lt;/strong&gt; section of our page then we may run into trouble with invalid markup when viewing in on-page editing mode in the CMS.&amp;nbsp; We can get around this by adding another attribute, hence:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;@Html.PropertyFor(x =&amp;gt; x.SomeContentArea, new { HasContainer = false, HasItemContainer = false, HasEditContainer = false } )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will get us out of trouble but, although the blocks in the Content Area are rendered, we cannot edit it in on-page editing and we&#39;ll have to switch to the properties view.&amp;nbsp; No big deal in my opinion.&lt;/p&gt;
&lt;p&gt;A huge thanks to &lt;strong&gt;Valdis Iljuconoks&lt;/strong&gt;, their solution worked a treat for the bug I was working on and I added it here in the hope that other people find it as useful as I did.&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/jon-sexton/dates/2021/6/how-to-easily-remove-the-extra-div-tags-for-content-areas/</guid>            <pubDate>Thu, 03 Jun 2021 11:06:22 GMT</pubDate>           <category>Blog post</category></item><item> <title>TinyMCE Table Templates</title>            <link>https://world.optimizely.com/blogs/jon-sexton/dates/2021/3/tinymce-template-tables/</link>            <description>&lt;h3&gt;&lt;strong&gt;Aim&lt;/strong&gt;.&lt;/h3&gt;
&lt;p&gt;Lately we had a requirement from one of our clients to enable the WYSIWYG editor on a page (XHtmlString property (TinyMCE)) in the CMS to cater for a set of &lt;strong&gt;preformed&lt;/strong&gt; table templates.&amp;nbsp; The notion was to allow content editors to enter data into a simple table in the WYSIWYG editor but, to make the task easier, they should be able to select what sort of table they require, as opposed to having to create one themselves.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Situation&lt;/strong&gt;.&lt;/h3&gt;
&lt;p&gt;By reducing the number of tools available in the WYSIWYG editor toolbar, to just &lt;strong&gt;bold&lt;/strong&gt;, &lt;em&gt;italic&lt;/em&gt;, undo, redo and a new template button (less is more), the content editor will be able to quickly complete the task without any unnecessary clutter on the WYSIWYG editor in question.&amp;nbsp; The new template button will enable the content editor to select what preformed template they require for the specific task.&amp;nbsp; This custom configuration of TinyMCE can then be applied to one or more page types.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Solution&lt;/strong&gt;.&lt;/h3&gt;
&lt;p&gt;So that&#39;s enough of the &#39;what&#39; and &#39;why&#39;, now for the &#39;how&#39;.&lt;/p&gt;
&lt;p&gt;Firstly, let&#39;s create a couple of (really simple) preformed template tables in HTML, thus:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;h5&amp;gt;Table title&amp;lt;/h5&amp;gt;
&amp;lt;table cellpadding=&quot;10&quot;&amp;gt;
    &amp;lt;thead&amp;gt;
    &amp;lt;tr&amp;gt;
        &amp;lt;td&amp;gt;Document&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;Part Number&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;Type&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;Size&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;Date Added&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
    &amp;lt;/thead&amp;gt;
    &amp;lt;tbody&amp;gt;
    &amp;lt;tr&amp;gt;
        &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
    &amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;table cellpadding=&quot;10&quot;&amp;gt;
    &amp;lt;thead&amp;gt;
    &amp;lt;tr&amp;gt;
        &amp;lt;td&amp;gt;Document&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;Part Number&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;Type&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
    &amp;lt;/thead&amp;gt;
    &amp;lt;tbody&amp;gt;
    &amp;lt;tr&amp;gt;
        &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;
        &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
    &amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note &lt;/strong&gt;that the first template caters for a heading, outside of the main table, and five columns, whereas the second template caters for only three columns.&amp;nbsp; Also note that we have added the &#39;cellpadding=&quot;10&quot;&#39; attribute to the table tag (I know &#39;cellpadding&#39; is an obsolete attribute but trust me, it&#39;ll work just fine for what we want it for); these settings will prove to be useful for the content editors later on and, because of the CSS we use, this additional attribute &lt;span style=&quot;text-decoration:&amp;#32;underline;&quot;&gt;will not&lt;/span&gt; affect the final rendering of the table(s).&amp;nbsp; Save these templates (as &lt;strong&gt;.html&lt;/strong&gt;) into a suitable location in your project.&lt;/p&gt;
&lt;p&gt;Next we&#39;re going to create the configuration for TinyMCE to use these templates.&amp;nbsp; Open up the configuration file for TinyMCE; ours looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    [InitializableModule]
    [ModuleDependency(typeof(TinyMceInitialization))]
    public class TinymceCustomInitialization : IConfigurableModule
    {
        public void Initialize(InitializationEngine context) { }

        public void Uninitialize(InitializationEngine context) { }

        public void ConfigureContainer(ServiceConfigurationContext context)
        {
            context.Services.Configure&amp;lt;TinyMceConfiguration&amp;gt;(config =&amp;gt;
            {
                // Default configuration settngs go here...
            });
        }
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Directly under the default configuration settings we&#39;re going to clone the default settings and apply a stylesheet that contains the relevant CSS for final rendering, thus:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;        public void ConfigureContainer(ServiceConfigurationContext context)
        {
                // Default configuration settngs go here...

                // Create a simple version of tinyMce, with just the bare necessities and a template button.
                var simpleConfiguration = config.Default().Clone()
                    .ContentCss(&quot;/static/css/default.css&quot;)
            });
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, let&#39;s add the settings for the two templates and add these settings as a plugin, thus:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;        public void ConfigureContainer(ServiceConfigurationContext context)
        {
            context.Services.Configure&amp;lt;TinyMceConfiguration&amp;gt;(config =&amp;gt;
            {
                // Default configuration settngs go here...

                // Create a simple version of tinyMce, with just the bare necessities and a template button.
                var simpleConfiguration = config.Default().Clone()
                    .ContentCss(&quot;/static/css/default.css&quot;)
                    .AddSetting(&quot;templates&quot;, new[]
                    {
                        new
                        {
                            title = &quot;Downloads template 1&quot;,
                            url = &quot;/static/html/templates/template1.html&quot;,
                            description = &quot;Template 1 for a preformed table&quot;
                        },
                        new
                        {
                            title = &quot;Downloads template 2&quot;,
                            url = &quot;/static/html/templates/template2.html&quot;,
                            description = &quot;Template for a preformed table&quot;
                        }
                    })
                    .AddPlugin(&quot;template&quot;)
            });
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note &lt;/strong&gt;that the settings name should be &#39;&lt;em&gt;templates&lt;/em&gt;&#39; and that the plugin name should be &#39;&lt;em&gt;template&lt;/em&gt;&#39;, this is &lt;strong&gt;IMPORTANT&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Finally, let&#39;s setup the toolbar and apply our simple TinyMCE configuration to a page type that&#39;s going to use it, thus:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;        public void ConfigureContainer(ServiceConfigurationContext context)
        {
            context.Services.Configure&amp;lt;TinyMceConfiguration&amp;gt;(config =&amp;gt;
            {
                // Default configuration settngs go here...

                // Create a simple version of tinyMce, with just the bare necessities and a template button.
                var simpleConfiguration = config.Default().Clone()
                    .ContentCss(&quot;/static/css/default.css&quot;)
                    .AddSetting(&quot;templates&quot;, new[]
                    {
                        new
                        {
                            title = &quot;Template 1&quot;,
                            url = &quot;/static/html/templates/template1.html&quot;,
                            description = &quot;Template 1 for a preformed table&quot;
                        },
                        new
                        {
                            title = &quot;Template 2&quot;,
                            url = &quot;/static/html/templates/template2.html&quot;,
                            description = &quot;Template 2 for a preformed table&quot;
                        }
                    })
                    .AddPlugin(&quot;template&quot;)
                    .Toolbar(&quot;bold italic | undo redo | template&quot;);

                // Assign this simple tinyMce configuration to the required XhtmlString property
                // on the required model.
                config.For&amp;lt;YourPageType&amp;gt;(x =&amp;gt; x.YourPropertyName, simpleConfiguration);
            });
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that&#39;s it folks!&amp;nbsp; Let&#39;s compile our code and see how it renders in edit mode in the CMS:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;fig.1&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/74215506c54e44adbda67d7b614d7ac4.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Note the simple toolbar configuration with the new template button.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;fig.2&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/c1bc11ec6b204a66a11a279cc734426b.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When the content editor clicks on the new template button they will be presented with a new modal window, which allows them to select a template to use.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;fig.3&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/e76f64ffde2249ed80c3372924b7a9bc.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;With the template selected the content editor is ready to enter their data.&amp;nbsp; Hey, but what&#39;s with that extra toolbar and where did it come from?&amp;nbsp; Well, because the template HTML contains a table, TinyMCE has detected this and has provided us with tools to be able to set the table properties, delete the table, add a new row above the current row in scope, add a new row beneath the current row in scope, delete the current row in scope, add a new column to the right of the current column in scope, add a new column to the left of the current column in scope and delete the current in scope, respectively.&lt;/p&gt;
&lt;p&gt;Needless to say, the content editors can edit the table title and column headings to their own requirements and can enter multiple table templates should they desire.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note &lt;/strong&gt;that because we used the old &#39;cellpadding=&quot;10&quot;&#39; attribute on the table tag in our template HTML, the cells are &#39;padded&#39; so the content editor has a clearer, less cluttered view of where their data is to go.&amp;nbsp; This setting is NOT carried over to the final rendering of the table, if your CSS file has correctly defined the table rendering of course.&amp;nbsp; As an extra aid a content editor may (temporarily) set the border attribute for the table to &quot;1&quot;; this can be set in the &#39;border&#39; attribute of the table properties toolbar item but it will need to be deleted/set to &quot;0&quot;, when they&#39;ve finished editiing the table data, as this setting WILL carry over to final rendering.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;fig.4&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/b0db87fd284a476b91e24218a4f6a938.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Final rendering.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;This solution provides a really lightweight, simple-to-use alternative to having to use a block to acheive the same result.&amp;nbsp; I&#39;d like to pay tribute to the article I found at &lt;a href=&quot;https://davidboland.site/blog/create-episerver-tinymce-default-templates&quot;&gt;https://davidboland.site/blog/create-episerver-tinymce-default-templates&lt;/a&gt; for giving me the inspiration for this solution.&lt;/p&gt;
&lt;p&gt;Feedback to this post will be welcomed and appreciated.&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/jon-sexton/dates/2021/3/tinymce-template-tables/</guid>            <pubDate>Sat, 27 Mar 2021 15:58:31 GMT</pubDate>           <category>Blog post</category></item><item> <title>How to set primary (default) and secondary (optional) fonts for TinyMCE in EPiServer CMS 11</title>            <link>https://world.optimizely.com/blogs/jon-sexton/dates/2021/2/how-to-set-primary-default-and-secondary-optional-fonts-for-tinymce-in-episerver-cms-11/</link>            <description>&lt;h3&gt;&lt;strong&gt;Aim&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The client requirements were to have the generic TinyMCE editors (XhtmlString), across the EPiServer CMS (v11.20) site, to give content editors the ability to have only primary (default) and secondary (optional) custom fonts to use.&amp;nbsp; Either font is to be used in the following block formats:&lt;/p&gt;
&lt;p&gt;P, H1, H2, H3, H4, H5 and H6&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Situation&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;There was a lot of information on the Net, in various EPiServer blogs, on how to set styles (font colours, font sizes, etc.) but very little up-to-date information on how to change the actual fonts to custom ones.&amp;nbsp; After a lot of research, and even more trial and error, we finally came up with a workable solution.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;The first thing to do is to make changes to the &amp;lsquo;editorStyles.css&amp;rsquo; file. Ours was in &amp;lsquo;[EPiServer website]\ClientResources\Styles\editorStyles.css&amp;rsquo;.&amp;nbsp; We needed to add two custom fonts, &amp;lsquo;Solomon&amp;rsquo; and &amp;lsquo;BornReady&amp;rsquo; and create CSS classes that use them, hence:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code&gt;@font-face {
    font-family: Solomon;
    font-style: normal;
    font-weight: 400;
    font-stretch: normal;
    src: url(/assets/main/fonts/solomon/normal_normal_normal.woff2) format(&quot;woff2&quot;),
         url(/assets/main/fonts/solomon/normal_normal_normal.woff) format(&quot;woff&quot;)
}

@font-face {
    font-family: BornReady;
    font-style: normal;
    font-weight: 400;
    font-stretch: normal;
    src: url(/assets/main/fonts/bornreadyupright/normal_normal_normal.woff2) format(&quot;woff2&quot;),
         url(/assets/main/fonts/bornreadyupright/normal_normal_normal.woff) format(&quot;woff&quot;)
}

.bornready {font-family: BornReady,sans-serif,Arial,Verdana,&quot;Trebuchet MS&quot;;}

.solomon {font-family: Solomon,sans-serif,Arial,Verdana,&quot;Trebuchet MS&quot;;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note the use of fallback fonts in the CSS classes (good practice).&lt;/p&gt;
&lt;p&gt;2. The next thing to do is to create an initialisation module for the TinyMCE editor and configure it so the TinyMCE editor operates as per the client&amp;rsquo;s requirements.&lt;/p&gt;
&lt;p&gt;Ours looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[ModuleDependency(typeof(TinyMceInitialization))]
public class CustomTinyMceInitializationModule : IConfigurableModule
{
    public void Initialize(InitializationEngine context)
    {}

    public void Uninitialize(InitializationEngine context)
    {}

    public void ConfigureContainer(ServiceConfigurationContext context)
    {
        context.Services.Configure&amp;lt;TinyMceConfiguration&amp;gt;(config =&amp;gt;
        {
            config.Default()
            .AddEpiserverSupport()
            .AddSetting(&quot;paste_as_text&quot;, true)
            .AddSetting(&quot;paste_webkit_styles&quot;, true)
            .AddSetting(&quot;paste_merge_formats&quot;, true)
            .AddSetting(&quot;paste_remove_styles_if_webkit&quot;, true)
            .AddPlugin(&quot;epi-link epi-dnd-processor epi-personalized-content help image fullscreen lists searchreplace hr table paste media code&quot;)
            .Toolbar(&quot;bold italic superscript subscript quote citation bullist numlist undo redo | styleselect formatselect removeformat&quot;,
                &quot;epi-link epi-unlink anchor | cut copy paste pastetext pasteword | table | code | image epi-image-editor | epi-personalized-content | fullscreen &quot;)
            .ContentCss(&quot;/ClientResources/Styles/editorStyles.css&quot;)
            .BodyClass(&quot;solomon&quot;)
            .StyleFormats(new {title = &quot;BornReady font&quot;, selector = &quot;p,h1,h2,h3,h4,h5,h6&quot;, classes = &quot;bornready&quot;})
            .BlockFormats(&quot;Paragraph=p;Header 1=h1;Header 2=h2;Header 3=h3;Header 4=h4;Header 5=h5;Header 6=h6;&quot;);
        });
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Points to note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;Add &amp;lsquo;&lt;strong&gt;styleselect&amp;rsquo;&lt;/strong&gt; and &amp;lsquo;&lt;strong&gt;formatselect&amp;rsquo;&lt;/strong&gt; items to the toolbar setting.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;Tell TinyMCE what stylesheet to use. This is done by adding the line, &amp;lsquo;&lt;strong&gt;.ContentCss(&amp;ldquo;/ClentResources/Styles/editorStyles.css&amp;rdquo;)&lt;/strong&gt;&amp;rsquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;Set the primary (default) font. This is done by adding the line, &amp;lsquo;&lt;strong&gt;.BodyClass(&amp;ldquo;solomon&amp;rdquo;)&lt;/strong&gt;&amp;rsquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;Set the styles available for the &amp;lsquo;styleselect&amp;rsquo; toolbar item as a new object, hence:&lt;strong&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;.StyleFormats( new{title=&amp;rdquo;&lt;/strong&gt;[name of font]&lt;strong&gt;&amp;rdquo;, selector=&amp;rdquo;&lt;/strong&gt;[comma separated list of block formats to apply the font to (see below)]&lt;strong&gt;&amp;rdquo;, classes=&amp;rdquo;bornready&amp;rdquo;})&lt;/strong&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;Finally, set the block formats available for the &amp;lsquo;formatselect&amp;rsquo; toolbar item as a semicolon separated list of string values, hence:&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;.BlockFormats(&amp;ldquo;Paragraph=p;Heading 1=h1;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6&amp;rdquo;);&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;3. Now compile your solution, refresh the CMS in your browser and try out the TinyMCE editor. You should be able to add a paragraph that will be displayed in the default font, in our case, &amp;lsquo;solomon&amp;rsquo; but, by highlighting this text and selecting the &amp;lsquo;BornReady font&amp;rsquo; from the &amp;lsquo;styleselect&amp;rsquo; dropdown in the toolbar, the text will be displayed in the secondary font.&amp;nbsp; By selecting different options from the &amp;lsquo;formatselect&amp;rsquo; dropdown in the toolbar, you can change your text from paragraph to H1, H2, and so on.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/81f2ee1a0308400cb302c9371606669c.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Line 1, paragraph in secondary font.&lt;/p&gt;
&lt;p&gt;Line 2, H2 in primary font.&lt;/p&gt;
&lt;p&gt;Line 3, H2 in secondary font.&lt;/p&gt;
&lt;p&gt;Line 4, paragraph in primary font.&lt;/p&gt;
&lt;p&gt;So, there we go, a workable solution to the problem.&amp;nbsp; Please feel free to leave comments.&lt;/p&gt;
&lt;p&gt;Thanks to Sam Brooks of dotcentric Ltd for his assistance in arriving to the final solution.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/jon-sexton/dates/2021/2/how-to-set-primary-default-and-secondary-optional-fonts-for-tinymce-in-episerver-cms-11/</guid>            <pubDate>Fri, 26 Feb 2021 11:02:18 GMT</pubDate>           <category>Blog post</category></item></channel>
</rss>