Join our next Developer Virtual Meetup – Live Q&A, Project Showcase, Swag raffle, and more 🔥

Guidance on converting HTML tables to portable objects in Sanity CMS.

7 replies
Last updated: Mar 12, 2023
Hello Everyone,I’m migrating my blog website from Netlify to Sanity CMS. I’m using this package sanity/block-tools to convert the blog body content HTML to portable objects. Everything is working fine except for the HTML Tables. Can you please guide me on how can I achieve it?
Mar 8, 2023, 6:38 PM
user M
Mar 8, 2023, 6:41 PM
Hello Everyone, Any response here?
Mar 12, 2023, 7:54 PM
Hey
user S
have you tried the the
blockContentType
option to define a custom block type for tables?
Schema example:

// schema.js
import { ... } from '@sanity/schema-builder'

export default createSchema({
  // ...
  types: [
    // ...
    {
      name: 'table',
      type: 'object',
      title: 'Table',
      fields: [
        {
          name: 'rows',
          type: 'array',
          of: [
            {
              type: 'array',
              of: [
                {
                  type: 'string',
                },
              ],
            },
          ],
        },
      ],
      preview: {
        select: {
          rows: 'rows',
        },
        prepare(rows) {
          return {
            title: `Table (${rows.length} rows)`,
            subtitle: rows.map((r) => r.join(' | ')).join('\n'),
          }
        },
      },
    },
  ],
})
Mar 12, 2023, 7:58 PM
user B
No I have not tried. Here’s my current Schema:

export default {
  name: "bodyPortableText",
  type: "array",
  title: "Post body",
  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",
                validation: (Rule) =>
                  Rule.uri({
                    allowRelative: true,
                    scheme: ['http', 'https', 'mailto', 'tel', '/'],
                  }),
              },
            ],
          },
          {
            name: 'internalLink',
            type: 'object',
            title: 'Internal link',
            fields: [
              {
                name: 'reference',
                type: 'reference',
                title: 'Reference',
                to: [
                  { type: 'post' },
                  // other types you may want to link to
                ]
              }
            ]
          }
        ],
      },
      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 },
    },
  ],
};
Mar 12, 2023, 8:01 PM
Here’s the html table that I would like to convert into the portable objects and fit it in the above schema.

<table style="width:100%;border-collapse:collapse;table-layout:fixed;height:747px;border:1px solid #99acc2"><tbody><tr style="height:37px"><td style="width:33.3333%;height:37px;padding:4px;border:1px solid #99acc2"><strong>Lender</strong>
      </td><td style="width:33.3333%;height:37px;padding:4px;border:1px solid #99acc2"><strong>Average Rate
          Spread</strong></td><td style="width:33.3333%;height:37px;padding:4px;border:1px solid #99acc2"><strong>Amount Originated in
          2021</strong></td></tr><tr style="height:37px"><td style="width:33.3333%;height:37px;padding:4px;border:1px solid #99acc2">PennyMac Servicing</td><td style="width:33.3333%;height:37px;padding:4px;border:1px solid #99acc2">-0.39</td><td style="width:33.3333%;height:37px;padding:4px;border:1px solid #99acc2"><span>
        </span><span>$17,514,705,000</span></td></tr><tr style="height:37px"><td style="width:33.3333%;height:37px;padding:4px;border:1px solid #99acc2"><br><span>Home Point
          Financial</span></td><td style="width:33.3333%;height:37px;padding:4px;border:1px solid #99acc2">-0.36</td><td style="width:33.3333%;height:37px;padding:4px;border:1px solid #99acc2">$7,247,505,000</td></tr></tbody></table>
Mar 12, 2023, 8:03 PM
try this revised Schema….notice the use of blockContent
export default {
name: “bodyPortableText”,
type: “array”,
title: “Post body”,
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”,
validation: (Rule) =&gt;
Rule.uri({
allowRelative: true,
scheme: [‘http’, ‘https’, ‘mailto’, ‘tel’, ‘/’],
}),
},
],
},
{
name: ‘internalLink’,
type: ‘object’,
title: ‘Internal link’,
fields: [
{
name: ‘reference’,
type: ‘reference’,
title: ‘Reference’,
to: [
{ type: ‘post’ },
// other types you may want to link to
]
}
]
}
],
},
of: [
{
type: “authorReference”,
},
{
type: “table”,
title: “Table”,
blockContentType: “table”,
},
],
},
// 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 },
},
],
// Define the custom block type for tables
types: [
{
name: “table”,
type: “object”,
fields: [
{
name: “content”,
type: “array”,
of: [{ type: “row” }],
},
],
},
{
name: “row”,
type: “object”,
fields: [
{
name: “cells”,
type: “array”,
of: [{ type: “cell” }],
},
],
},
{
name: ”
Mar 12, 2023, 8:05 PM
Thanks
user B
you made my day.
Mar 12, 2023, 8:51 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?