👀 Our most exciting product launch yet 🚀 Join us May 8th for Sanity Connect

Issue with using JSDOM in htmlToBlocks function for server-side API

3 replies
Last updated: Jul 12, 2023
Hi All,I am using htmlToBlocks function to convert my html data from quill text editor to blocks in order to upload them to sanity. It was working perfectly in client side but I wanted to move it to serverside api. In order to do it, I have added JSDOM as parseHtml option. I put below code together but keep getting error '- error TypeError: Cannot read properties of undefined (reading 'firstElementChild')' it does not even go into deserialize since I do not see my log for deserialize. I am using Nextjs 13. Also I know it is not related to JSDOM because it works perfectly outside htmlToBlocks.
I have tried JSDOM(html).window.document instead of JSDOM(html) but this raise another error. "- error ReferenceError: window is not defined" after looping thru all of the elements of the html
Any ideas?


const convertedBlocks = htmlToBlocks(content, blockContentType, {
                parseHtml: (html) => new JSDOM(html),
                rules: [
                    // Special rule for code blocks
                    {
                        deserialize(el, next, block) {
                            console.log('el: ', el);
                            if (el.tagName?.toLowerCase() === 'img') {
                                const src = el.getAttribute('src');
                                const alt = el.getAttribute('alt');
                                console.log('el: ', el);
                                // Create block object for each image
                                const imageBlock = {
                                    _type: 'image',
                                    asset: {
                                        _type: 'reference',
                                        _ref: 'toReplace' + index
                                    }
                                    // Add any other relevant metadata fields
                                };
                                imageLibrary.push(src);
                                index++;
                                return block(imageBlock);
                            }
                            // Continue with default conversion for other elements
                            return undefined;
                        }
                    }
                ]
            });
Error for JSDOM(html).window.document


- error ReferenceError: window is not defined
    at Module.getRandomValues (webpack-internal:///(sc_server)/./node_modules/get-random-values-esm/index.mjs:7:5)
    at whatwgRNG (webpack-internal:///(sc_server)/./node_modules/@sanity/block-tools/lib/index.js:185:37)
    at randomKey (webpack-internal:///(sc_server)/./node_modules/@sanity/block-tools/lib/index.js:193:12)
    at normalizeBlock (webpack-internal:///(sc_server)/./node_modules/@sanity/block-tools/lib/index.js:1145:15)
    at eval (webpack-internal:///(sc_server)/./node_modules/@sanity/block-tools/lib/index.js:1201:56)
    at Array.map (<anonymous>)
    at htmlToBlocks (webpack-internal:///(sc_server)/./node_modules/@sanity/block-tools/lib/index.js:1201:43)
    at eval (webpack-internal:///(sc_server)/./lib/sanityDatabaseFunctions.js:55:102)
    at new Promise (<anonymous>)
    at convertHtmlToBlocks (webpack-internal:///(sc_server)/./lib/sanityDatabaseFunctions.js:49:12)
    at eval (webpack-internal:///(sc_server)/./lib/sanityDatabaseFunctions.js:110:34)
    at new Promise (<anonymous>)
    at writeNewSolutionData (webpack-internal:///(sc_server)/./lib/sanityDatabaseFunctions.js:105:12)
    at POST (webpack-internal:///(sc_server)/./src/app/api/submit-design/route.js:13:110)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:244:37)
Error for JSDOM(html)


- error TypeError: Cannot read properties of undefined (reading 'firstElementChild')
    at preprocessGDocs (webpack-internal:///(sc_server)/./node_modules/@sanity/block-tools/lib/index.js:426:18)
    at eval (webpack-internal:///(sc_server)/./node_modules/@sanity/block-tools/lib/index.js:463:9)
    at Array.forEach (<anonymous>)
    at preprocess (webpack-internal:///(sc_server)/./node_modules/@sanity/block-tools/lib/index.js:462:19)
    at HtmlDeserializer.parseHtml (webpack-internal:///(sc_server)/./node_modules/@sanity/block-tools/lib/index.js:1131:25)
    at HtmlDeserializer.deserialize (webpack-internal:///(sc_server)/./node_modules/@sanity/block-tools/lib/index.js:951:30)
    at htmlToBlocks (webpack-internal:///(sc_server)/./node_modules/@sanity/block-tools/lib/index.js:1201:25)
    at eval (webpack-internal:///(sc_server)/./lib/sanityDatabaseFunctions.js:55:102)
    at new Promise (<anonymous>)
    at convertHtmlToBlocks (webpack-internal:///(sc_server)/./lib/sanityDatabaseFunctions.js:49:12)
    at eval (webpack-internal:///(sc_server)/./lib/sanityDatabaseFunctions.js:109:34)
    at new Promise (<anonymous>)
    at writeNewSolutionData (webpack-internal:///(sc_server)/./lib/sanityDatabaseFunctions.js:104:12)
    at POST (webpack-internal:///(sc_server)/./src/app/api/submit-design/route.js:13:110)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:244:37)
Jun 16, 2023, 4:10 PM
Please don’t create multiple threads when you’re already getting help in one.
You’ll want to look up the differences between client side and server side and why you don’t have access to the DOM on the server side.
Jun 16, 2023, 6:13 PM
I was not sure if all community would see my question to you on the other thread. I understand why I do not have access to the DOM on the server side but I do not understand why it does not work when I provide JSDOM as parseHtml option. It should parse the html in JSDOM and use it's DOM for sub functions. Am I missing something? By the way JSDOM works outside htmlToBlocks function. When I use jsdom(html).Window.document as parseHtml(both options are in documentation weirdly), it processes my html but stuck at normalizeBlock-&gt; getRandomValues called by htmlToBlocks
Jun 16, 2023, 6:19 PM
Thank you very much for your help on this. I have finalized my project and shared it in i-made-thisSolved the above issue with this
https://github.com/sanity-io/sanity/issues/4595#issuecomment-1604050213
Jul 12, 2023, 10:47 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?