DEV Community

loading...

Sanity Datatable serializer for 11ty sites

katiekodes profile image Katie Originally published at katiekodes.com on ・2 min read

Playing with the 11ty (Eleventy) code from Bryan Robinson's sanity-eleventy-blog repo (from Sanity's official tutorial on 11ty) and a Sanity project started using the built-in "blog" dataset, I got stuck adding Fred Jens's sanity-datatable Sanity Studio plugin to the body rich-text editor of Sanity because 11ty threw an error: "Unknown block type 'table', please specify a serializer for it in the serializers.types prop."

The solution was to edit the object exported from Bryan's utils/serializers.js as module.exports, adding the following to it:

,
    table: ({node}) => `
<table>
  <thead>
    <tr><th scope="col">${node.rows[0].cells.join('</th><th scope="col">')}</th></tr>
  </thead>
  <tbody>
    ${node.rows.slice(1).map(row => '<tr><td>' + row.cells.join('</td><td>') + '</td></tr>').join('\r\n    ')}
  </tbody>
</table>
      `

This is because the datatable plugin returns data that looks like this:

{
  "_key": "abc123",
  "_type": "table",
  "rows": [
    {
      "_key": "def456",
      "_type": "column",
      "cells": ["Row 1 Cell 1 Value Here", "Row 1 Cell 2 Value Here"]
    },
    {
      "_key": "ghi789",
      "_type": "column",
      "cells": ["Row 2 Cell 1 Value Here", "Row 2 Cell 2 Value Here"]
    },
    {
      "_key": "zyx987",
      "_type": "column",
      "cells": ["Row 3 Cell 1 Value Here", "Row 3 Cell 2 Value Here"]
    }
  ]
}

What my JavaScript transforms Sanity's output into is this snippet of (hopefully accessible) HTML-formatted text:

<table>
  <thead>
    <tr><th scope="col">Row 1 Cell 1 Value Here</th><th scope="col">Row 1 Cell 2 Value Here</th></tr>
  </thead>
  <tbody>
    <tr><td>Row 2 Cell 1 Value Here</td><td>Row 2 Cell 2 Value Here</td></tr>
    <tr><td>Row 3 Cell 1 Value Here</td><td>Row 3 Cell 2 Value Here</td></tr>
  </tbody>
</table>

If you didn't want to treat your first row as a table header, the "serializer" would be a bit shorter:

,
    table: ({node}) => `
<table>
  ${node.rows.map(row => '<tr><td>' + row.cells.join('</td><td>') + '</td></tr>').join('\r\n  ')}
</table>
      `

I'm sure there're more elegant ways to do this if you actually know modern JavaScript, but I'm proud of myself for getting this working at all without asking a friend, so here stands my code in all its clunkiness.

Discussion (0)

pic
Editor guide