0

My setup is GatsbyJS with Ghost as an external CMS and I am trying to load all images of a page locally.

So I found a blog post showing me a way to do this for one image, which worked for me: https://ghost.joonaviertola.com/optimize-ghost-images-in-gatsby/

I then thought I could also do this for multiple images and instead of linking one image to the node, create an array with all the images. I first tried this for just one image. Linking the image directly and pushing the image into an array on the node.

imgUrls = [...]; // list of absolute URLs of remote images
node.localImages = [];

// test with only one image first
if (imgUrls.length) {
    const fileNode = await createRemoteFileNode({
        url: imgUrls[0],
        store,
        cache,
        createNode,
        parentNodeId: node.id,
        createNodeId
    });

    if (fileNode) {
        node.localImage___NODE = fileNode.id;
        node.localImages.push(fileNode);
    }
}

In the GraphQL explorer, I now see this:

enter image description here

So node.localImage___NODE = fileNode.id is working and I get the image linked to the node, with childImageSharp inside.

node.localImages.push(fileNode) on the other hand seems to work, because I get an array with (in this case) one image inside. Only the childImageSharp and childMarkdownRemark are missing, which are the parts I wanted to begin with.

Right now I'm not sure if this whole approach is completely wrong or if I'm just a tiny step away. Any thoughts?

Rolf B
  • 61
  • 7

1 Answers1

1
exports.onCreateNode = async ({ node, getNode, actions, store, createNodeId, cache }) => {
    const { createNodeField, createNode } = actions;
    // Download image and create a File node with gatsby-transformer-sharp.
    if ([`GhostPost`, `GhostPage`].includes(node.internal.type)) {
        // Parse HTML and get all images
        if (node.html) {
            const regex = /<img.+?src="(.+?)".+?>/g;

            let imgUrls = [];
            let matches = regex.exec(node.html);
            while (matches) {
                imgUrls.push(matches[1]);
                matches = regex.exec(node.html);
            }

            const localImages = [];

            for (const imgUrl of imgUrls) {
                if (!['.jpg', '.jpeg', '.png'].some(item => imgUrl.toLowerCase().includes(item))) {
                    continue;
                }

                const fileNode = await createRemoteFileNode({
                    url: imgUrl,
                    store,
                    cache,
                    createNode,
                    parentNodeId: node.id,
                    createNodeId
                });

                if (fileNode) {
                    localImages.push(fileNode.id);
                }
            }

            node.localImages___NODE = localImages;
        }
    }
};

Not sure if this is the right/best approach, but it seems to work now. Creating a GhostPost node per post from Ghost, extracting all images (jpg and png) from the html, creating image nodes of them and linking them to the GhostPost node.

Rolf B
  • 61
  • 7