Opticon Stockholm is on Tuesday September 10th, hope to see you there!
Opticon Stockholm is on Tuesday September 10th, hope to see you there!
If I needed to solve this I would consider the following approach:
Parsing the rendered document and updating all of the header tags as a middleware would probably be more costly for the page request.
We commonly do this on render through the views, not through middleware.
We prefer this over modifying the content stored to the database.
Main reason being that we would then still need to parse the HTML content to figure out which anchor links there are to be able to render something like a TOC list or other markup.
We had an RTE extension that might worth a shot in your case. This is not tested but should work fine.
using System.IO;
using System.Web.Mvc;
using EPiServer.Core;
using EPiServer.Editor;
using EPiServer.Web.Mvc.Html;
using HtmlAgilityPack;
namespace Ecommerce.Site.Extensions
{
public static class XhtmlStringExtensions
{
/// <summary>
/// Parses the XhtmlString for Image tags and sets them to lazy load
/// </summary>
public static string FormatRichText(this XhtmlString html, ViewContext context)
{
// html is null when the TinyMce is not initialize (creating new block etc.)
if (html == null) return string.Empty;
// Load up Epi's HtmlHelper and ask it to render results
var hh = new HtmlHelper(context, new ViewPage());
string epiRenderingResult;
using (var writer = new StringWriter())
{
hh.ViewContext.Writer = writer;
hh.RenderXhtmlString(html);
writer.Flush();
epiRenderingResult = writer.ToString();
}
if (PageEditing.PageIsInEditMode)
return epiRenderingResult;
// once results are rendered, load up HtmlAgilityPack and have it parse results
var doc = new HtmlDocument();
doc.LoadHtml(epiRenderingResult);
var headings = doc.DocumentNode.SelectNodes("//h1");
if (headings == null)
return epiRenderingResult;
foreach (var heading in headings)
{
heading.SetAttributeValue("id", $"{yourValue}");
}
var outerHtml = doc.DocumentNode.OuterHtml;
return outerHtml; // return out the new resulting HTML
}
}
}
The other way I could think of doing it on razor files itself if isn't not always coming through RTE. For all RTEs you can create an InitializationModule that looks for all XhtmlString usages and use this extension.
I think it's not too bad to add it to the first H1 found using JS.
There you can also add tabindex="0" to make it focusable.
You should not have tabindex="0" in the markup from the server.
I would like to add id attributes to all header tags for a specific site, so that all heading can be linked to.
Example:
...should be changed to...
...that it can be linked to with #main-heading. Ideally this should work for all headings, including those in text properties
What is the best way of solving this? Middleware and regex-search-replace?