I’d like to extend the tiptap editor with a custom field that would store HTML meant to be directly rendered on the frontend.
So currently the rendering part looks like this:
import { generateHTML } from "@tiptap/html";
const htmlContent = generateHTML(proseMirrorDocument, [
StarterKit,
RelatedArticleNode,
InArticleImageNode,
//...
]);
In this list I define custom nodes for rendering elements. According to the previous example the new component would look something like this:
import { Node } from '@tiptap/core';
export const CustomHTMLNode = Node.create({
// ...
renderHTML({ HTMLAttributes }) {
// ...
return ['div',{}, customHTML];
With the twist that I had to have my customHTML
properly rendered on the frontend.
Basically the equivalent of
<div dangerouslySetInnerHTML={{ __html: customHTML }} />
Any idea?
Achieving this with TipTap Node objects is not possible.
I ended up modifying the generated HTML with JSDOM. (Feel free to use the tool of your liking, cheerio
, etc.), it’s not so clean but at least simple from now on. With JSDOM, setting the innerHTML
property of the element makes the content inside render like usual HTML.
// Load the HTML content into JSDOM
const dom = new JSDOM(htmlContent);
// Use the DOM API to select and update elements
const document = dom.window.document;
const divs = document.querySelectorAll('div.custom-html');
// Update the content of each selected div
divs.forEach(div => {
div.innerHTML = div.textContent;
});
// Serialize the updated HTML back to a string
htmlContent = dom.serialize();