- Notifications
You must be signed in to change notification settings - Fork37
Render Contentful Rich Text fields to native strings and views
License
contentful/rich-text-renderer.swift
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
When integrated into an iOS project, this library renders ContentfulRichText toNSAttributedString with nativeUIView embedded in the text. This is made possible because this library is built on top ofTextKit, and provides a powerful plugin system to render Contentful entries and assets that are embedded inRichText.
What is Contentful?
Contentful provides content infrastructure for digital teams to power websites, apps, and devices. Unlike a CMS, Contentful was built to integrate with the modern software stack. It offers a central hub for structured content, powerful management and delivery APIs, and a customizable web app that enable developers and content creators to ship their products faster.
platform:ios,'11.0'use_frameworks!pod'ContentfulRichTextRenderer'
You can also useCarthage for integration by adding the following to yourCartfile:
github "contentful/rich-text-renderer.swift"And then run the following command in the terminal:
carthage update --platform iOS --use-xcframeworksAdd all the XCFrameworks fromCartfile/Build directory into your project manually.
The main entry point for the library is theRichTextViewController. You can either use it standalone, or subclass it. Theview instance forRichTextViewController has aUITextView subview that uses a customNSLayoutManager andNSTextContainer to lay out text, enabling text to wrap around nested views for embedded assets and entries, and also enabling blockquote styling analogous to that seen on websites.
import Contentfulimport RichTextRendererimport UIKitclassViewController:RichTextViewController{privateletclient=ContentfulService() /// Your service fetching data from Contentful.init(){ /// Default configuration of the renderer.letconfiguration=DefaultRendererConfiguration()letrenderer=RichTextDocumentRenderer(configuration: configuration) super.init(renderer: renderer)}requiredinit?(coder aDecoder:NSCoder){fatalError("init(coder:) has not been implemented")}overridefunc viewDidLoad(){ super.viewDidLoad()fetchContent()}privatefunc fetchContent(){ client.fetchArticle{[weak self] resultinswitch result{case.success(let article):self?.richTextDocument= article.contentcase.failure(let error):break}}}}
You can configure how the renderer renders content by modifyingDefaultRendererConfiguration instance or by creating new one conforming toRendererConfiguration protocol.
Initializing instance ofDefaultRendererConfiguration provides a configuration with sane defaults. Simply create an instance, then mutate it to further customize the rendering.
You can render custom views forResourceLinkBlock nodes by passing a view provider to the configuration object.
varconfiguration=DefaultRendererConfiguration() configuration.resourceLinkBlockViewProvider=ExampleBlockViewProvider()
Below is the example implementation on the view provider that is cappable of renderingCar model and theAsset.
structExampleViewProvider:ResourceLinkBlockViewProviding{func view(for resource:Link, context:[CodingUserInfoKey:Any])->ResourceLinkBlockViewRepresentable?{switch resource{case.entryDecodable(let entryDecodable):iflet car= entryDecodableas?Car{returnCarView(car: car)}returnnilcase.entry:returnnilcase.asset(let asset):guard asset.file?.details?.imageInfo!=nilelse{returnnil}letimageView=ResourceLinkBlockImageView(asset: asset) imageView.backgroundColor=.gray imageView.setImageToNaturalHeight()return imageViewdefault:returnnil}}}finalclassCarView:UIView,ResourceLinkBlockViewRepresentable{privateletcar:CarvarsurroundingTextShouldWrap:Bool=falsevarcontext:[CodingUserInfoKey:Any]=[:]publicinit(car:Car){self.car= car super.init(frame:.zero)lettitle=UILabel(frame:.zero) title.text="🚗"+ car.model+" 🚗" title.translatesAutoresizingMaskIntoConstraints=falseaddSubview(title) title.topAnchor.constraint(equalTo: topAnchor).isActive=true title.trailingAnchor.constraint(equalTo: trailingAnchor).isActive=true title.bottomAnchor.constraint(equalTo: bottomAnchor).isActive=true title.leadingAnchor.constraint(equalTo: leadingAnchor).isActive=true title.sizeToFit() frame= title.bounds backgroundColor=.lightGray}requiredinit?(coder:NSCoder){fatalError("init(coder:) has not been implemented")}func layout(with width:CGFloat){}}
Inline elements in theRichTextDocument can be rendered asNSMutableAttributedString object.
varconfiguration=DefaultRendererConfiguration() configuration.resourceLinkInlineStringProvider=ExampleInlineStringProvider()
Below is the implementation of the inline string provider that rendersCat type.
import Contentfulimport RichTextRendererimport UIKitfinalclassExampleInlineStringProvider:ResourceLinkInlineStringProviding{func string( for resource:Link, context:[CodingUserInfoKey:Any])->NSMutableAttributedString{switch resource{case.entryDecodable(let entryDecodable):iflet cat= entryDecodableas?Cat{returnCatInlineProvider.string(for: cat)}default:break}returnNSMutableAttributedString(string:"")}}privatefinalclassCatInlineProvider{staticfunc string(for cat:Cat)->NSMutableAttributedString{returnNSMutableAttributedString( string:"🐈\(cat.name) ❤️", attributes:[.foregroundColor:UIColor.rtrLabel])}}
The library has been implemented the way that you can provide custom renderers for specific node types.
Simply create a class that inherits from one of the default renderers and write your own. Then attach to aDefaultRenderersProvider and that's it.
finalclassExampleParagraphRenderer:ParagraphRenderer{typealiasNodeType=Paragraphoverridefunc render( node:Paragraph, rootRenderer:RichTextDocumentRendering, context:[CodingUserInfoKey:Any])->[NSMutableAttributedString]{ /// Your code for rendering paragraphs.}}
letconfiguration=DefaultRendererConfiguration()varrenderersProvider=DefaultRenderersProvider() renderersProvider.paragraph=ExampleParagraphRenderer()letrenderer=RichTextDocumentRenderer( configuration: configuration, nodeRenderers: renderersProvider) super.init(renderer: renderer)
The best way to get acquainted with using this library in an iOS app is to check out the example that is a part of this repository. In particular, pay attention to the view provider and inline provider in order to learn how to render entries and assets that are embedded in the rich text.
This repository is published under theMIT license.
We want to provide a safe, inclusive, welcoming, and harassment-free space and experience for all participants, regardless of gender identity and expression, sexual orientation, disability, physical appearance, socioeconomic status, body size, ethnicity, nationality, level of experience, age, religion (or lack thereof), or other identity markers.
About
Render Contentful Rich Text fields to native strings and views
Topics
Resources
License
Code of conduct
Contributing
Security policy
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Uh oh!
There was an error while loading.Please reload this page.
Contributors13
Uh oh!
There was an error while loading.Please reload this page.