Relatude Help

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('?') ? "&amp;" : "?", "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;