delivery-sdk-net icon indicating copy to clipboard operation
delivery-sdk-net copied to clipboard

Proposal: New way of rendering rich-text

Open petrsvihlik opened this issue 4 years ago • 2 comments

Theme:

  • Improve rich-text rendering for .NET

Goals:

  • improve and unify the link & asset resolution (#258 - resolution of all data-* attributes, #243 - other attributes of , #193 - asset URLs)
  • promote ASP.NET display templates to a best practice
  • strengthen the object model (IRichTextContent was an early attempt to achieve that but it's far from complete)
  • separate responsibilities and clean up the code (e.g. bug #257 - resolving rich-text into different types, #231 - mixing rendering and resolution approaches)

All related issues: https://github.com/Kentico/kontent-delivery-sdk-net/labels/rich-text

Supported scenarios:

  • ASP.NET Display Templates
  • Flattening of rich-text for search indexing purposes, etc.
  • Provide ways to adjust content before rendering

Current solution:

  • We offer two types of rich-text resolution:
    • string-based - involves multiple types of resolvers for links, inline items, etc.
    • IRichTextContent-based - an object-like approach that combines hierarchical approach (for inline content items and assets) and string-based HTML rendering (for links)

Proposed solution:

  • Let the IRichTextContent be the default type for rich-text elements and provide an additional layer for flattening it to a string.

Detailed proposition:

  • Make the logic of RichTextContentConverter part of the ModelProvider
  • Adjust the logic of RichTextContentConverter to treat links as objects (=do not apply string-based resolution) => links, assets, inline content items will be treated the same - as objects
  • Provide resolution methods for all three type of objects ContentLinkResolver, ContentAssetResolver, InlineContentItemResolver
    • public string ResolveToString(T model) -> ability to flatten the object to string
    • public T Resolve(T model) -> ability to adjust model's properties
  • Enrich the existing models for Links and Asset with a collection for supplying additional attributes (such as class or target), also add properties for some of the most common attributes (such as URL)
  • Move all string-based resolution from the ModelProvider to a separate class (e.g. HtmlResolver)
  • Remove the --structuredmodel option from the code generator and leave it true by default

Example code:

var articleResponse = await deliveryClient.GetItemAsync<Article>("on-roasts");
Article article = articleResponse.Item;
IRichTextContent richText = article.Body;
// Contains links, assets, strongly typed inline content items...already processed by `T Resolve(T model)`
// Ready to be passed to ASP.NET MVC Display Templates
IEnumerable<IRichTextBlock> blocks = richText.Blocks; 


HtmlResolver resolver = new HtmlResolver(new XYZLinkResolver(), new ABCAssetResolver()...); // Or build via DI
string flattenedHtml = resolver.ToString(blocks, articleResponse.LinkedItems);

petrsvihlik avatar Jan 22 '21 14:01 petrsvihlik

It looks like this new approach might resolve this as the IContentLinkUrlResolver moves from ModelProvider to HtmlResolver,

But currently, because the IContentLinkUrlResolver is instantiated via DI in the ModelProvider, which is in turn used by the DeliveryClient, Its currently impossible to have a IDeliveryClient instance injected within a custom IContentLinkUrlResolver implementation (it creates a circular dependency), eg;

    public class CustomContentLinkUrlResolver : IContentLinkUrlResolver
    {
        public CustomContentLinkUrlResolver(IDeliveryClient client)
        {
        }
    }

which in our case we want, (and I would think is a pretty general requirement?) to query Kontent's subpages hierarchy and build the url for a particular content item passed to the Url Resolver.

jrkd avatar Mar 24 '22 04:03 jrkd

Thanks for pointing this out, we will take this into consideration.

MiroKentico avatar Mar 31 '22 10:03 MiroKentico