2

RichText in Contentful is deserialized to Document type, and Document is converted to MarkupString type for use. (I created an extension method). When using the "code" tag in Contentful's RichTextEditor, the "pre" tag does not exist in the parent element, so line breaks and indentation are ignored by the browser.

Is there a way to add a parent element to any HTML tag?

        public static MarkupString ToHtml(this Document doc)
        {
            var renderer = new HtmlRenderer();
            var html = renderer.ToHtml(doc).GetAwaiter().GetResult();
            return (MarkupString)html;
        }

using Blazor ServerSide.

    <div>
        @entry.Content.ToHtml()
    </div>

Model

    public class ContentfulEntry
    {
        public SystemProperties Sys { get; set; }
        public string Title { get; set; }
        public Document Content { get; set; }
        public string Description { get; set; }
        public Asset Cover { get; set; }
    }
Ethree 8ch
  • 63
  • 4

1 Answers1

0

Implement a custom renderer for Text:

public class CustomTextRenderer : IContentRenderer
{
    /// <summary>
    /// The order of this renderer in the collection.
    /// </summary>
    public int Order { get; set; } = 90;

    /// <summary>
    /// Whether or not this renderer supports the provided content.
    /// </summary>
    /// <param name="content">The content to evaluate.</param>
    /// <returns>Returns true if the content is a textual node, otherwise false.</returns>
    public bool SupportsContent(IContent content)
    {
        return content is Text;
    }

    /// <summary>
    /// Renders the content to a string.
    /// </summary>
    /// <param name="content">The content to render.</param>
    /// <returns>The content as a string.</returns>
    public string Render(IContent content)
    {
        var text = content as Text;
        var sb = new StringBuilder();

        if (text.Marks != null)
        {
            foreach (var mark in text.Marks)
            {
                if(mark == "code">) {
                    sb.Append("<pre>");                    
                }
                  sb.Append($"<{MarkToHtmlTag(mark)}>");
            }
        }

        sb.Append(text.Value);

        if (text.Marks != null)
        {
            foreach (var mark in text.Marks)
            {
                sb.Append($"</{MarkToHtmlTag(mark)}>");
                if(mark == "code">) {
                    sb.Append("</pre>");                    
                }
            }
        }

        return sb.ToString();
    }

    private string MarkToHtmlTag(Mark mark)
    {
        switch (mark.Type)
        {
            case "bold":
                return "strong";
            case "underline":
                return "u";
            case "italic":
                return "em";
            case "code":
                return "code";
        }

        return "span";
    }

    /// <summary>
    /// Renders the content asynchronously.
    /// </summary>
    /// <param name="content">The content to render.</param>
    /// <returns>The rendered string.</returns>
    public Task<string> RenderAsync(IContent content)
    {
        return Task.FromResult(Render(content));
    }
}

Then add it to your HTML renderers collection of renderers:

public static MarkupString ToHtml(this Document doc)
    {
        var renderer = new HtmlRenderer();
        renderer.AddRenderer(new CustomTextRenderer());
        var html = renderer.ToHtml(doc).GetAwaiter().GetResult();
        return (MarkupString)html;
    }

Note that the Order property controls the order in which renderers are evaluated. This means this custom renderer will be evaluated before the default ones.

Robban
  • 6,729
  • 2
  • 39
  • 47