Reputation: 1021
We have a very restricted rich text editor for our client. We only allow a handful of standard tags. We want all styling to be dictated by the CSS we've built for the site. They are not allowed to deviate.
We've removed most options form the toolbar and only having specific tags in the dropdown, but we recently added CSS to the editor so that the text in the editor is styled like it is on the page to make it easier for authors to visualize. Now under certain circumstances, it will insert span tags with inline styles like:
<h2><span style="font-family: Georgia, 'Times New Roman', serif; color: #232b37;">text</span></h2>
It seems to be pulling our CSS in. Is there a way to configure it to just not do this? Thanks.
Upvotes: 3
Views: 4287
Reputation: 499
No, you cannot change this behavior by configuration. What you could do is add an item:saving event handler, that removes any unwanted tags like these span tags whenever a content editor saves the item. It is not the nicest solution but at least it works. I often use it to clean out unwanted (empty) paragraph tags the rich text editor tends to add.
<event name="item:saving">
<handler type="ExampleProject.Events.RemoveUnwantedTags, ExampleProject" method="OnItemSaving" />
</event>
Removing empty P-tags is easy, but for your solution you could use a regex to replace any tags with an inline style attribute (which should be unique anyway).
Here's a mockup code template you could use to replace all rich text editor field values in an item for this event handler:
public class RemoveUnwantedTags
{
public void OnItemSaving(object sender, EventArgs args)
{
var item = Event.ExtractParameter(args, 0) as Item;
if (item == null)
{
return;
}
foreach (Field field in item.Fields)
{
if (!field.TypeKey.Equals("rich text", StringComparison.InvariantCultureIgnoreCase))
{
continue;
}
var content = field.Value;
if (!string.IsNullOrEmpty(content))
{
content = content.Trim();
// replace whatever you want over here
using (new SecurityDisabler())
{
item.Editing.BeginEdit();
field.Value = content;
item.Editing.EndEdit();
}
}
}
}
}
Upvotes: 4
Reputation: 11
Of course it's tempting to make all sort of item:save pipelines because they just work. But don't forget about more specific pipelines that can actually hook into the moment after you click on the Accept button and the moment Sitecore put's the richtext in the field.
<!-- Transforms markup from rich text fields before the Rich Text Editor loads it. -->
<loadRichTextContent/>
<!-- Transforms markup from the Rich Text Editor before saving it as a rich text field value. -->
<saveRichTextContent/>
Both are pipelines that work great for this purpose. An example implementation of this can be found at https://techmusingz.wordpress.com/2014/06/14/wrapping-rich-text-value-in-paragraph-tag-in-sitecore/
copy/paste from the website mentioned above:
public void Process(SaveRichTextContentArgs args)
{
if (!(args.Content.Trim().StartsWith("<p>") && args.Content.Trim().EndsWith("</p>")))
args.Content = "<p>" + args.Content + "</p>";
}
I personally don't like real string operations on the output so I would recommend handling the richtext content with HtmlAgilityPack (which Sitecore comes with) or use a XDocument.
Example by myself with HtmlAgilityPack that removes script and style elements:
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
// Strip output from all kinds of stuff
doc.DocumentNode.Descendants()
.Where(n => n.Name == "script" || n.Name == "style")
.ToList()
.ForEach(n => n.Remove());
An even better solution would be to parse and clean it up with a good and solid HtmlSanitizer. https://github.com/mganss/HtmlSanitizer
Make sure you create some unittests to wrap the pipeline and test it to its extends.
Best Regards,
Alex van Wolferen
Upvotes: 1