Headless CMS > Extending Functionality
Create a Rich Text Content Renderer
Learn how to implement a custom rich text content renderer, or enhance the default one.
This feature is available since Webiny v5.39.0.
- how to add a custom rich text content renderer
Overview
Headless CMS contains a rich text content field, which allows users to create content using a rich text editor. By default, Webiny uses the Lexical Editor, but developers are able to implement whatever editor they want for their projects. This means that the data stored into the database can, and most likely will, be very different between various rich text editors.
The Headless CMS GraphQL schema exposes a format
parameter on rich text fields, to allow content consumers to request a specific format to be returned to them from the API. Out of the box, Webiny provides an HTML renderer for its default Lexical editor implementation. However, your project might use a different rich text editor, or you might want to support a different output format, for example, markdown.
To inspect the implementation of our built-in Lexical-to-HTML renderer, see the source code on Github.
Code examples below demonstrate the creation of plugin instances which need to be registered in the apps/api/graphql/src/index.ts
. Simply import your plugins, and append them to the bottom of the plugins array in the handler definition.
Create a Custom Renderer
The code example is pointing to a file which doesn’t yet exist in your project. Create this file, or place the code into a different location of choice.
To create a custom renderer, create a plugin similar to the one shown in the code example below.
This creates a renderer that is executed when the content consumer specifies html
as the output format of the rich text field in the GraphQL query. myHTMLRenderer
is a fictional function to demonstrate the use of the plugin. The implementation of the actual HTML (or any other format) rendering will depend on the rich text editor that you use in your project, and the format you’re rendering to.
You’ve probably noticed the use of the dynamic import, and the webpackChunkName
inline comment. We highly recommend you use code splitting to only load your renderer when it’s actually being used. This will reduce the size of the main code bundle that the Lambda function will have to process for common request processing. The webpackChunkName
is recommended for easier debugging, as this name will be used as the chunk name, when the code bundle is built.
Intercept Existing Renderer
Sometimes, you might want to let the default renderer do its job, but fine tune the output before returning it to the consumer. This way, you can build multiple plugins that form a chain of transformations.
When there are multiple plugins registered to handle the same format, a chain is created, where the last plugin registered will be the first one executed. You will be able to call the next plugin in the chain using the next
callback. This way you can completely intercept all previous plugins, and either skip them all together, or execute them at will.