Unlock seamless workflows and faster delivery with our latest releases – get the details

Discussion on importing WordPress content into Sanity using `sanity exec` and block-tools.

9 replies
Last updated: Nov 9, 2022
Hello! Is there some sample code/examples/docs for how to run a script to import existing content using
sanity exec
? Everything I’ve found so far seems to be code meant to run in a browser (and when trying to import my schema I get errors looking for the
window
global)
Nov 9, 2022, 12:46 AM
Here's an example of a script that manipulates content that uses
sanity exec
. What source are you trying to migrate from? Can you share the code you've tried?
Nov 9, 2022, 12:49 AM
Nov 9, 2022, 12:52 AM
I’m trying to pull in WordPress content using WPGraphQL and then import it using block-tools
Nov 9, 2022, 12:53 AM
The import piece isn’t there because it keeps failing just on importing the schema
Nov 9, 2022, 12:54 AM
Got it! I think I might know what the issue is. What does your
schemaData
look like?
Sidenote: if I'm wrong,
this Wordpress to Sanity migration repo will come in handy for you.
Nov 9, 2022, 12:58 AM
I added my
schema.js
to the Gist
Nov 9, 2022, 1:00 AM
Thanks. You don't need to concat all of your schema types here . the
.compile()
method takes an object that contains a block content array. So, your
schemaData
can be as simple as this:
const schemaData = {
  name: 'myBlog',
  types: [
    {
      type: 'object',
      name: 'blogPost',
      fields: [
        {
          title: 'Title',
          type: 'string',
          name: 'title',
        },
        {
          title: 'Body',
          name: 'body',
          type: 'array',
          of: [{ type: 'block' }],
        },
      ],
    },
  ],
}
You should be able to pass that directly to your
Schema.compile
.
Nov 9, 2022, 1:11 AM
Yep, that did it!
But if I want to try to parse WordPress blocks into Sanity block types, do I need to copy those into this other schema? (For instance, I want to convert
<figure class="wp-block-gallery">
into a
gallery
object)
Nov 9, 2022, 1:26 AM
Dope! You don't need to specify that schema during the migration but you will need to create a rule for the deserialization of those other types. For example, this would handle code and images for that default schema:
export const blockContentType = defaultSchema
  .get('blogPost')
  .fields.find(field => field.name === 'body').type;

export const generateBlocks = field =>
  blockTools.htmlToBlocks(field, blockContentType, {
    rules: [
      // Special rule for code blocks
      {
        deserialize(el, next, block) {
          if (el.tagName.toLowerCase() != 'pre') {
            return undefined;
          }
          const code = el.children[0];
          const childNodes =
            code && code.tagName.toLowerCase() === 'code'
              ? code.childNodes
              : el.childNodes;
          let text = '';
          childNodes.forEach(node => {
            text += node.textContent;
          });
          // Return this as an own block (via block helper function), instead of appending it to a default block's children
          return block({
            _type: 'code',
            language: 'javascript',
            text: text,
          });
        },
      },
      {
        deserialize (el, next, block) {
          if (el.tagName === 'IMG') {
            return block({
                children: [],
                _sanityAsset: `image@${el
                  .getAttribute('src')
                  .replace(/^\/\//, 'https://')}`
            })
          }

          if (
            el.tagName.toLowerCase() === 'p' &&
            el.childNodes.length === 1 &&
            el.childNodes.tagName &&
            el.childNodes[0].tagName.toLowerCase() === 'img'
          ) {
            return block({
                _sanityAsset: `image@${el.childNodes[0]
                  .getAttribute('src')
                  .replace(/^\/\//, 'https://')}`
            })
          }
          // Only convert block-level images, for now
          return undefined
        }
      }
    ],
  });
You'll need that other schema you created in the Studio, though! You can just add it to the Studio's schema folder.
Nov 9, 2022, 1:33 AM

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?