Rewriting
HtmlRewriter.Rewrite copies HTML through and splices in only what a handler changes. A handler can
rewrite attribute values, insert markup before a tag, and replace text.
// adds a campaign to every external link in an article body
sealed class CampaignLinks(string campaign) : IHtmlRewriteHandler {
public string? RewriteAttribute(ReadOnlySpan<char> tag, ReadOnlySpan<char> attribute, ReadOnlySpan<char> value) =>
tag.Equals("a", StringComparison.OrdinalIgnoreCase)
&& attribute.Equals("href", StringComparison.OrdinalIgnoreCase)
&& value.StartsWith("https://")
? string.Concat(value, value.Contains('?') ? "&" : "?", "utm_campaign=", campaign)
: null; // null leaves the value as it is
public string? InsertBefore(ReadOnlySpan<char> tag, bool isEndTag) => null;
}
var html = HtmlRewriter.Rewrite(article.Body, new CampaignLinks("autumn"));| Member | Does |
|---|---|
IHtmlRewriteHandler.RewriteAttribute |
a new value for an attribute, or null |
IHtmlRewriteHandler.TryWriteAttribute |
the same, written into an HtmlValueWriter without allocating (optional) |
IHtmlRewriteHandler.InsertBefore |
markup to insert before a start or end tag, or null |
IHtmlRewriteHandler.OnText, RewriteText |
see or replace text outside script and style (optional) |
HtmlRewriteOptions |
RewriteInsideConditionalComments (on) and MaxConditionalDepth (4), for Outlook's conditional comments in email |
HtmlRewriter.ToText(html) |
the visible text: tags stripped, script and style dropped, whitespace collapsed, entities decoded |
HtmlEntities.Encode, Decode |
escape the five HTML special characters; decode numeric and common named entities |
A new attribute value is escaped so that it cannot end the attribute. Markup from InsertBefore and
text from RewriteText are written exactly as given, so encode anything a user supplied with
HtmlEntities.Encode first.
HtmlRewriter.ToText suits search snippets and meta descriptions:
var text = HtmlRewriter.ToText(article.Body);
article.MetaDescription = text.Length > 160 ? text[..157] + "…" : text;