New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add responsiveness support for images uploaded through Netlify CMS #2995

Closed
kripod opened this Issue Nov 22, 2017 · 13 comments

Comments

Projects
None yet
4 participants
@kripod
Contributor

kripod commented Nov 22, 2017

Currently, the recommended way to upload images to a static website through Netlify CMS is by using the static folder, which does not offer any support for responsiveness. I would like to ask for a way to make CMS-managed assets queryable through GraphQL.

@KyleAMathews

This comment has been minimized.

Contributor

KyleAMathews commented Nov 22, 2017

You could setup gatsby-source-filesystem to read files from the static folder.

@kripod

This comment has been minimized.

Contributor

kripod commented Nov 22, 2017

I think that gatsby-source-filesystem wouldn't help much here. Basically, I'm trying to read a thumbnail attribute which points to an image like /images/uploads/test.png as an absolute URL (so, the aforementioned file is physically stored at static/images/uploads/test.png). The thumbnail attribute gets read as a string instead of being transformed into an image object.

@kripod

This comment has been minimized.

Contributor

kripod commented Nov 30, 2017

@KyleAMathews How can I transform a String node into an ImageSharp node? I just set up gatsby-source-filesystem to read files from the static folder, but need to access those images' nodes by a public path.

@kripod

This comment has been minimized.

Contributor

kripod commented Nov 30, 2017

Basically, I have a string property called thumbnail in some of my markdown files' frontmatter, and I want to transform them into ImageSharp nodes:

E.g. from /assets/uploads/conference.jpg into an ImageSharp node with the following absolute path: C:/Development/Projects/mvk-web/static/assets/uploads/conference.jpg (where C:/Development/Projects/mvk-web is my Gatsby project root)

@KyleAMathews

This comment has been minimized.

Contributor

KyleAMathews commented Nov 30, 2017

Use onCreateNode to create a link to the File node — can give you a code sample if that's not enough a hint.

@kripod

This comment has been minimized.

Contributor

kripod commented Nov 30, 2017

It would be great if you could provide me a code sample. Thank you in advance!

@KyleAMathews

This comment has been minimized.

Contributor

KyleAMathews commented Nov 30, 2017

// In your gatsby-node.js
// Not tested
exports.onCreateNode = ({ node, getNode, getNodes, boundActionCreators }) => {
  const { createNode, createNodeField } = boundActionCreators
  if (node.internal.type === `MarkdownRemark`) {
    // Create link
    // Find absolute path of linked path
    const pathToFile = path.resolve(getNode(node.parent).absolutePath, node.frontmatter.thumbnail)
    // Find ID of File node
    const fileNode = getNodes().find(n => n.absolutePath === pathToFile)
    createNodeField({
      node,
      name: `imageLink___NODE`,
      value: fileNode.id,
    })
  }
  // Transform the new node here and create a new node or
  // create a new node field.
}
@kripod

This comment has been minimized.

Contributor

kripod commented Nov 30, 2017

Thank you for your kind assistance! Although the createNodeField method didn't work as expected, I ended up with the following code, based on yours:

exports.onCreateNode = ({
  node, getNode, getNodes, boundActionCreators,
}) => {
  const { createNodeField, createParentChildLink } = boundActionCreators;

  if (node.internal.type === 'MarkdownRemark') {
    const slug = createFilePath({ node, getNode, basePath: 'pages' });
    createNodeField({
      node,
      name: 'slug',
      value: slug,
    });

    // Attach thumbnail's ImageSharp node by public path if necessary
    if (typeof node.frontmatter.thumbnail === 'string') {
      // Find absolute path of linked path
      const pathToFile = path
        .join(__dirname, 'static', node.frontmatter.thumbnail)
        .split(path.sep)
        .join('/');

      // Find ID of File node
      const fileNode = getNodes().find(n => n.absolutePath === pathToFile);

      if (fileNode != null) {
        // Find ImageSharp node corresponding to the File node
        const imageSharpNodeId = fileNode.children.find(n => n.endsWith('>> ImageSharp'));
        const imageSharpNode = getNodes().find(n => n.id === imageSharpNodeId);

        // Add ImageSharp node as child
        createParentChildLink({ parent: node, child: imageSharpNode });
      }
    }
  }
};

It would be great if there was a more in-depth documentation about linking nodes (or even their properties) together.

@kripod kripod closed this Nov 30, 2017

@martynhoyer

This comment has been minimized.

Contributor

martynhoyer commented Apr 30, 2018

@kripod Do you have any example of this working that I could clone and test with? I'm trying the same thing but not having much luck.

@kripod

This comment has been minimized.

Contributor

kripod commented Apr 30, 2018

@martynhoyer Yeah, it can be found here along with a working website: https://github.com/simonyiszk/mvk-web/blob/master/gatsby-node.js

@martynhoyer

This comment has been minimized.

Contributor

martynhoyer commented Apr 30, 2018

Thanks @kripod! Much appreciated. Unfortunately I'm still stuck... it seems the getNodes() call doesn't have any of the images in it so const fileNode = getNodes().find(n => n.absolutePath === pathToFile); always returns undefined. The images show in allImageSharp and allFile in GraphiQL so they seem to be getting processed correctly.

Any quick suggestions, or shall I open a new issue?

@waywardm

This comment has been minimized.

Contributor

waywardm commented Jul 26, 2018

Netlify Image Solution

To allow using gatsby image processing plugins on your frontmatter

In each Markdown file

relpath: ../../..  
logo: /static/images/myimage.png

In gatsby-config.js

Under plugins add the code to access the static image folder as files

{
      resolve: 'gatsby-source-filesystem',
      options: {
        name: 'static/images',
        path: `${__dirname}/static/images`,
      },
    },

In gatsby-node.js

Create a new nodeField for each image needed

exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions;

if (node.internal.type === 'MarkdownRemark') {

if (node.frontmatter.relpath && node.frontmatter.logo ) {

      const logopath = node.frontmatter.relpath + node.frontmatter.logo

      createNodeField({
        node,
        name: 'logolink',
        value: logopath
      });
    }

}

}

In config.yml

Add media folder

media_folder: "static/images" 

In each collection in config.yml

State relative path for each collection that require an image in the frontmatter as a hidden field that user doesn't need to modify

- {label: "Relative Path", name: "relpath", widget: "hidden", default: "../../.."}

Query in Graphql

{
  allMarkdownRemark {
    edges {
      node {
        id
        frontmatter {
          title
        }
        fields {
          logolink {
            childImageSharp {
              id
            }
          }
        }
      }
    }
  }
}
@kripod

This comment has been minimized.

Contributor

kripod commented Jul 29, 2018

Thank you for the tip, @waywardm!

I just came across an article about a similar situation:
https://blog.alexluong.com/generate-gatsby-image-sharp-from-an-image-url/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment