Empty p tags is being generated
I read that rich text would remove the unnecessary empty <p></p> tags generated from the text editor. But for some reason, I'm still getting p tags.
Here's what my sample code looks like
const options = {
renderNode: {
[BLOCKS.HEADING_1]: (node, children) => <h1>{children}</h1>,
[BLOCKS.HEADING_5]: (node, children) => <h5>{children}</h5>,
[BLOCKS.EMBEDDED_ASSET]: (node) => {
const fileUrl = node.data.target.fields.file['en-US'].url
return (
<ContentfulFixedAsset
fileUrl={fileUrl}
/>
)
}
}
}
documentToReactComponents(richText, options)
What am i doing wrong?
Contentful Rich Text Editor adds a trailing paragraph to a document. None of the renderers removes empty paragraphs from the document.
@sbezludny - Is that the intended functionality of the Contentful RTE? If so, do you happen to know the rationale behind doing so?
seeing this as well. It should be a bug. It makes me nervous to remove the last "p" on render.
Has anyone been able to solve this issue?
This is a temp work around that im using right now. I parse the rich text data before i send to the component
function stripTrailingParagraphNodes(richtext) {
let shouldStop = false;
const reversedContent = [...richtext.json.content].reverse();
richtext.json.content = reversedContent
.filter(node => {
if (!shouldStop) {
if (node.nodeType === "paragraph") {
const [{ value }] = node.content;
if (value.trim()) {
shouldStop = true;
return true;
}
return false;
} else {
shouldStop = true;
return true;
}
}
return true;
})
.reverse();
return richtext;
}
export default function RichTextRenderer({ richText }) {
if (!richText) return null;
let processedRichText = richText;
try {
processedRichText = stripTrailingParagraphNodes(richText);
} catch (e) {}
return documentToReactComponents(processedRichText.json, rendererOptions);
}
Honestly the easiest work-around is CSS, and what I use is simple.
CSS: p:empty { display: none; }
Any paragraph tag that is empty, hide it. You can use this universally like the above. Or more specifically wrap your displayed Contentful richtext entries in a div classed as such.
.richtext > p:empty { display:none; }
This can be problematic for clients who like to add vertical space with p tags but it's better than having my layout wrecked by either the content editor or the CMS.
This is a bit of a nuisance problem, so I understand why it's not high on the priorities, hope the above workaround helps!
@coreysyms that's what I was doing all this time but then I changed my layout a bit to use display:grid and row-gap to add spacing between the paragraphs and then things broke.
We have the same issue, and it causes an extra unexpected (and unwanted) padding in our case ! Thanks @coreysyms for the css fix
Wow I should have googled it first, thanks @coreysyms !
Just spent 30 minutes writing a recursive function to remove the empty objects from the content array where 1 line of css was enough.
Hi This option for Paragraph worked for me:
[BLOCKS.PARAGRAPH]: (node, children) => (children != '') ? <p>{children}</p> : '',
I am able to solve it with this check. Hope it will be helpful for the next poor soul.
renderNode: {
[BLOCKS.PARAGRAPH]: (node, children) => {
return (children.length === 1 && children[0][1] !== '') || children.length > 1 ? <p>
{children}
</p> : null;
},
}
I suggest it must be fixed by the library as contentful richtext is adding extra text or paragraph nodes. Cheers!
I got it working (in TypeScript) using this:
[BLOCKS.PARAGRAPH]: (node, children) => {
const isEmptyChildren = children?.toString().trim() === ''
if (isEmptyChildren) return null
return <p>{children}</p>
},
Wondering how this has not been fixed with the issue being open since 2019
I would love a built in answer for this.
@MatheusRich's solution is the only one that worked for me as the p:empty doesn't help if you have :last-child CSS selectors.
Wondering about this issue as well.
@glennflanagan if taking css approach, you can use .rich-text *:empty to target all empty elements. Or even use .rich-text p:nth-last-of-type(1) &:empty if you want to target the last paragraph
For my purposes, I have been using this code.
[BLOCKS.PARAGRAPH]: (node, children) => {
if(node && Array.isArray(node.content) && node.content.length === 1 && node.content[0].value?.trim() === ""){
return null;
}
return <p>{children}</p>;
},
Note: I get an empty <span/> inside the <p/> tag, so the CSS p:empty will not work in my code.
Extra note:
The :has CSS selector (along with the :empty selector) was promising, but it is not supported in Firefox.
https://developer.mozilla.org/en-US/docs/Web/CSS/:has
p:has(> span:empty){
margin-bottom: 0;
}