✨Discover storytelling in the AI age with Pixar's Matthew Luhn at Sanity Connect, May 8th—register now

Converting portable text to markdown or HTML in Sanity page builder

12 replies
Last updated: Aug 10, 2022
Heyy all, I am pretty new to Sanity (sorry in advance!) .. I am trying to figure a few things out 🙂 I'd like to create a pageBuilder (using the example provided in the docs) and within that use a media type that has an image with content that uses portableText. I did see a post that suggest this won't work because of nested arrays, but as I am very unfamiliar with how things work I was hoping someone might be able to either point me in the right direction if it is possible or confirm if it isn't! If it is indeed possible - has anyone any examples of how to convert the portableText from the content field to markdown? I am using 11ty. Thanks!
Aug 10, 2022, 11:02 AM
For a page builder, you typically have two approaches for your schema:• Use portable text only, and have your various modules and images as embeddable blocks within your portable text. So you have one field, and everything in it.
• Have a variety of modules as an an array of objects. Still one field, but it’s structured as an array of module objects.
Aug 10, 2022, 11:05 AM
Thank you for the quick reply! Excuse my examples below, a lot is from using examples provided in the docs and I am quickly trying to piece together a proof of concept.
I'd like to take the second approach as I think it will be little but more management for how I eventually going to try and implement the page builder.

I have a document type of something generic like 'mypage'


// mypage.js

export default {
  name: 'mypage',
  type: 'document',
  title: 'mypage',
  fields: [
    {
      name: 'name',
      type: 'string',
      title: 'Name'
    },
    {
      name: 'slug',
      type: 'slug',
      title: 'Slug',
      description: 'Some frontends will require a slug to be set to be able to show the person',
      options: {
        source: 'name',
        maxLength: 96
      }
    },
    {
      name: 'pageBuilder',
      type: 'array',
      title: 'Page builder',
      of: [
        { type: 'hero' },
        { type: 'textWithIllustration' },
        { type: 'media' },
      ]
    }
  ]
}
The the 'media' object is using some fields provided in from various examples including one for the rich text.


 // media.js

export default {
	name: 'media',
	type: 'object',
	title: 'Media',
	fields: [
    {
			name: 'content',
			type: 'array',
			title: 'Content',
			of: [
				{
					type: 'block',
					title: 'Block',
					// Styles let you set what your user can mark up blocks with. These
					// corrensponds with HTML tags, but you can set any title or value
					// you want and decide how you want to deal with it where you want to
					// use your content.
					styles: [
						{ title: 'Normal', value: 'normal' },
						{ title: 'H1', value: 'h1' },
						{ title: 'H2', value: 'h2' },
						{ title: 'H3', value: 'h3' },
						{ title: 'H4', value: 'h4' },
						{ title: 'Quote', value: 'blockquote' }
					],
					lists: [{ title: 'Bullet', value: 'bullet' }, { title: 'Number', value: 'number' }],
					// Marks let you mark up inline text in the block editor.
					marks: {
						// Decorators usually describe a single property – e.g. a typographic
						// preference or highlighting by editors.
						decorators: [{ title: 'Strong', value: 'strong' }, { title: 'Emphasis', value: 'em' }],
						// Annotations can be any object structure – e.g. a link or a footnote.
						annotations: [
							{
								name: 'link',
								type: 'object',
								title: 'URL',
								fields: [
									{
										title: 'URL',
										name: 'href',
										type: 'url'
									}
								]
							}
						]
					},
					//of: [{ type: 'authorReference' }]
				},
				// You can add additional types here. Note that you can't use
				// primitive types such as 'string' and 'number' in the same array
				// as a block type.
				{
					type: 'mainImage',
					options: { hotspot: true }
				}
			]
		},
		{
			name: 'imageSize',
			type: 'string',
			title: 'Image Size',
			options: {
				list: [
					{ title: 'Small', value: 'small' },
					{ title: 'Large', value: 'large' }
				], // <-- predefined values
				layout: 'radio', // <-- defaults to 'dropdown'
			}
		},
		{
			name: 'imagePosition',
			type: 'string',
			title: 'Image Position',
			options: {
				list: [
					{ title: 'Start', value: 'start' },
					{ title: 'End', value: 'end' }
				], // <-- predefined values
				layout: 'radio', // <-- defaults to 'dropdown'
			}
		},
	],
}
I think that's correct, but I am getting stuck on how to then convert my 'content' to markdown. Obviously for some of the 'mypages' they may not have the media type within their page builder. And the ones that do I have been trying to get to work using
@sanity/block-content-to-markdown
without much success. But I wasn't able to find much in the way of documentation to help
Aug 10, 2022, 11:17 AM
To Markdown? You can’t do that.
Aug 10, 2022, 11:23 AM
Markdown is a standardized text format. It will not support your custom blocks/modules.
Aug 10, 2022, 11:23 AM
The
@sanity/block-content-to-markdown
is used to transform text content from a portable text field (array of blocks) into Markdown content. But this is not what you are doing here. First because you’re not using portable text (you have your own array of objects, not an array of blocks), and also because you have your own custom objects; it’s not really text that can be converted to Markdown.
Aug 10, 2022, 11:24 AM
I’m also curious why you would want to convert things to Markdown?
Aug 10, 2022, 11:24 AM
ah ok! that makes a lot more sense - something I had missed. Thank you for explaining! so I guess I wanted a way that editors could perhaps add their image but tap into rich text for the content, apply some headings, perhaps make text bold or add a link. That's then why I was trying to use markdown with
@sanity/block-content-to-markdown
as that was used in the example starter project for sanity with 11ty. I think I have just over complicated and confused myself!
Aug 10, 2022, 11:33 AM
Sorry, just one more question if I may 😬 Is it possible to convert to html instead? Using just regular portable text.
Aug 10, 2022, 12:23 PM
Aug 10, 2022, 12:46 PM
Thank you! I have been testing that out and it works great! I have an example working where portable text is used for a 'pageBody' field on my document type and I can see the html rendered as expected. The only thing I can't figure out, and perhaps this is incredibly obvious (😬 ) but how I would then use
toHTML
for portable text fields within my page builder modules. I have spent a couple of hours researching but can't seem to find any examples that cover that instance. No worries at all if you it's too much to ask. Really appreciate the help already!
Aug 10, 2022, 3:51 PM
You would have to pass the
components
option to map the type of objects that can appear in your portable text to an actual chunk of HTML. See that example: https://github.com/portabletext/to-html#customizing-components 🙂
Aug 10, 2022, 3:53 PM
ah perfect! thank you! I did experiment quickly with a similar example, but wasn't sure it was what I needed/wasn't sure it was the right rabbit hole! Again, much appreciated 🙂 I am going to explore this further
Aug 10, 2022, 3:56 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?