First, it’s about a blog with netilify and gatsby. I have a common blog, the post have a tile, slug, banner/top image and a body, that is a markdown.
The banner’s src is correctly translated from ‘static/images/image_name.png’ to ‘static/[hash]/[hash] /image_name.png’, but the image in the body not.
I’m using gatsby-transformer-remark to translate the markdown to html. The field declared as the name being ‘body’ is translated into html, and then the src of every img tag should be translated correctly.
I follow the docs describe in the plugins for gatsby-transformer-remark, gatsby-remark-relative-images and gatsby-remark-images. What can I have set up wrong?
config.yml
backend: name: git-gateway repo: ### branch: ### media_folder: "static/images" public_folder: "static/images" collections: - name: "blog" label: "Blog" folder: "content/blog" create: true slug: "{{year}}-{{month}}-{{day}}-{{slug}}" fields: - {label: "Layout", name: "layout", widget: "hidden", default: "blog"} - {label: "Title", name: "title", widget: "string"} - {label: "Publish Date", name: "date", widget: "datetime"} - {label: "Image", name: "image", widget: "image"} - {label: "Description", name: "description", widget: "markdown"} - {label: "Keywords", name: "keywords", widget: "string"} - {label: "Body", name: "body", widget: "markdown"} - label: "Post Author" name: "author" widget: "relation" collection: "authors" searchFields: ["title"] valueField: "title" - label: "Related Categories" name: "categories" widget: "relation" collection: "categories" searchFields: ["title"] valueField: "title" multiple: true - label: "Call to Action" name: "call" widget: "object" fields: - {label: "Url", name: "url", widget: "string"} - {label: "Banner", name: "banner", widget: "image"} - {label: "Aria Label", name: "aria", widget: "string", required: false} - name: "authors" label: "Authors" folder: "content/authors" create: true slug: "{{year}}-{{month}}-{{day}}-{{name}}-author" fields: - {label: "Full Name", name: "title", widget: "string"} - name: "categories" label: "Post Categories" folder: "content/categories" create: true slug : "{{year}}-{{month}}-{{day}}-{{name}}-category" fields: - {label: "Category Name", name: "title", widget: "string"}
gatsby-config.js
const netlifyCmsPaths = { resolve: `gatsby-plugin-netlify-cms-paths`, options: { cmsConfig: `/static/admin/config.yml`, }, } module.exports = { siteMetadata: { title: `###`, description: `###`, author: `####`, }, plugins: [ { resolve: `gatsby-source-filesystem`, options: { name: `images`, path: `${__dirname}/static/images`, }, }, netlifyCmsPaths, `gatsby-plugin-netlify-cms`, `gatsby-plugin-react-helmet`, { resolve: `gatsby-source-filesystem`, options: { name: `content`, path: `${__dirname}/content/blog`, }, }, 'gatsby-plugin-sharp', 'gatsby-transformer-sharp', { resolve: `gatsby-transformer-remark`, options: { plugins: [ "gatsby-remark-relative-images", { resolve: `gatsby-remark-images`, options: { maxWidth: 1500, } }, { resolve: `gatsby-remark-image-attributes`, }, `gatsby-remark-lazy-load`, ], }, }, '@bumped-inc/gatsby-plugin-optional-chaining', { resolve: `gatsby-plugin-manifest`, options: { name: `gatsby-starter-default`, short_name: `starter`, start_url: `/`, background_color: `#663399`, theme_color: `#663399`, display: `minimal-ui`, icon: `src/assets/images/icon.png`, // This path is relative to the root of the site. }, }, `gatsby-plugin-sass`, { resolve: 'gatsby-plugin-eslint', options: { test: /\.js$|\.jsx$/, exclude: /(node_modules|.cache|public|gatsby-*)/, stages: ['develop'], options: { emitWarning: true, failOnError: false } } }, { resolve: "gatsby-plugin-react-svg", options: { rule: { include: /src\/assets\/images\/svg/ } } } // this (optional) plugin enables Progressive Web App + Offline functionality // To learn more, visit: https://gatsby.dev/offline // `gatsby-plugin-offline`, ], }
gatsby-node,js
const path = require('path'); const { createFilePath } = require(`gatsby-source-filesystem`); const { fmImagesToRelative } = require('gatsby-remark-relative-images'); exports.onCreateNode = ({ node, getNode, actions }) => { const { createNodeField } = actions; fmImagesToRelative(node); if (node.internal.type === 'MarkdownRemark') { const slug = createFilePath({ node, getNode, }); createNodeField({ node, name: 'slug', value: `/blog/${slug.slice(12)}`, }); const fileNode = getNode(node.parent); createNodeField({ node, name: 'sourceInstanceName', value: fileNode.sourceInstanceName, }); } }; // Implement the Gatsby API “createPages”. This is called once the // data layer is bootstrapped to let plugins create pages from data. exports.createPages = async ({ graphql, actions, reporter }) => { const { createPage } = actions; const result = await graphql(` { posts: allMarkdownRemark(filter: { fields: { sourceInstanceName: { eq: "content" } } }) { edges { node { fields { slug } frontmatter { title description categories author date image { childImageSharp { fluid { src } } } keywords call { aria banner { childImageSharp { fluid { src } } } url } } html } } } } `); const posts = await graphql(`{ allFile(filter: { sourceInstanceName: { eq: "content" } }) { edges { node { childMarkdownRemark { frontmatter { date title description author image { childImageSharp { fluid(maxWidth: 1500) { src } } } } fields { slug } } } } } }`); // Handle errors if (result.errors) { reporter.panicOnBuild(`Error while running GraphQL query: get post on post view page.`); return; } if (posts.errors || !posts.data) { reporter.panicOnBuild(`Error while running GraphQL query: list posts on post view page .`); return; } // Create pages for each markdown file. const blogPostTemplate = path.resolve(`src/templates/blog-post.jsx`); result.data.posts.edges.forEach(({ node }) => { createPage({ path: node.fields.slug, component: blogPostTemplate, context: { slug: node.fields.slug, data: { ...node.frontmatter, html: node.html }, posts: posts.data.allFile.edges.map(edge => ({ post: edge.node.childMarkdownRemark.frontmatter, slug: edge.node.childMarkdownRemark.fields.slug, })), }, }); }); };