How to turn PortableText into plain text in Javascript?

2 replies
Last updated: Dec 7, 2020
Hi! Is there a quick and dirty way to turn PortableText into plain text in JS? I have text for a Gatsby page that’s being transformed by “
user U
/block-content-to-react” which works really well; but it would be nice to just have a plain-text version of the page content that I could put in my meta descriptions. I’m guessing that someone must have solved this before more elegantly than I would? Thanks!
AI Update

Yes, there's a quick and easy way to convert Portable Text to plain text in JavaScript! You have several options depending on your needs:

Quick Plain Text Function

For a simple, no-dependencies solution, you can use this helper function that extracts just the text content:

function toPlainText(blocks = []) {
  return blocks
    .map(block => {
      // If it's not a text block with children, return nothing
      if (block._type !== 'block' || !block.children) {
        return ''
      }
      // Loop through the children spans and join the text strings
      return block.children.map(child => child.text).join('')
    })
    .join('\n\n')
}

This traverses the top-level blocks in your Portable Text array and joins the text from all children, which is perfect for meta descriptions!

NPM Package Option

If you prefer an npm package, check out the @portabletext/toolkit package which includes a toPlainText utility function. There's also a community recipe for Portable Text to plain text on the Sanity website with the same approach.

Using with Your Gatsby Setup

Since you're already using block-content-to-react for rendering, you can add this plain text function alongside it. Just pass your Portable Text content through toPlainText() before setting it as your meta description:

const metaDescription = toPlainText(pageContent.body)

The function handles non-text blocks gracefully by filtering them out, so you'll get clean plain text that's perfect for SEO meta tags.

Hey Dan, you might find this useful, credit goes to Sanity team because I just pinched it from the portableText documentation, I use all the time for previews:

export default function toPlainText(blocks = []) {
  return blocks
    .map(block => {
      if (block._type !== 'block' || !block.children) {
        return ''
      }
      return block.children.map(child => child.text).join('')
    })
    .join('\n\n');
}
This works perfectly. Thanks.

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?