How to use Gatsby to display a folder of images and markdown files

走远了吗. 提交于 2021-01-29 05:50:36

问题


So I'm very new to Gatsby, react, GraphQL, etc. In the past I've used pure CSS, HTML, and javascript to make my sites. Although, I was interested in Gatsby and the capabilities of it, so I decided to challenge myself and learn it.

I'm putting together a portfolio site for myself and for ease of updating, I would like to be able to add new projects through creating new folders, running a build script, and dropping the built site into my FTP.

This is how my folder structure for projects is set up:

-src
--projects
---1-daido-moriyama
----1-dm-frontcover.jpg
----2-dm-spread.jpg
----3-dm-backcover.jpg
----project-metadata.md
[...]
---2-lunch-from-a-care-package
----1-lf-wordmark.png
----2-lf-logo.png
----3-lf-poster.jpg
----project-metadata.md
[...]

The site is a single page, so no need to create new pages for each project. I just have them sorted into numbered folders because that would be the easiest to update for myself.

Ideally I would want to take the title and description from each project's markdown file, and put the title in an h3, the description in a p, and then display the images in a div, which when styled will become a carousel.

Mockup of the design

My current progress

I've been running some tests and have been able to access the markdown files using allMarkdownRemark, and the images using allImageSharp. It was hacky, but it worked, the only problem is that it was displaying all of the images, and not just the images needed for each project. Say, I have 8 images in a project, and 5 in another, it would display all 13 images.

Is there a way to do what I'm trying to do with Gatsby? Or should I just give up and move back to Jekyll…

gatsby-config.js:

module.exports = {
  siteMetadata: {
    title: 'J.C.R.'
  },
  plugins: [
    'gatsby-plugin-react-helmet',
    'gatsby-plugin-sass',
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        name: 'projects',
        path: `${__dirname}/src/projects/`
      }
    },
    'gatsby-transformer-remark',
    'gatsby-transformer-sharp',
    'gatsby-plugin-sharp',
    `@dream-bit-de/gatsby-plugin-better-page-tree`
  ]
}

gatsby-node.js:

const path = require('path')

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

    if (node.internal.type === 'MarkdownRemark') {
        const slug = path.basename(path.dirname(node.fileAbsolutePath, '.md'))
        createNodeField({
            node,
            name: 'slug',
            value: slug
        })
    }
}

Work component:

import React from 'react'
import { graphql, useStaticQuery } from 'gatsby'
import Img from 'gatsby-image'

const Work = () => {
    const data = useStaticQuery(graphql`
        query {
            allMarkdownRemark(
                sort: { order: ASC, fields: [frontmatter___position]}
            ) {
            edges {
                node {
                    frontmatter {
                        title
                        description
                    }
                    fields {
                        slug
                    }
                }
            }
            }
            allFile (
            filter: { 
                ext: {eq: ".jpg"}
            },
            sort: { 
                order: ASC, 
                fields: [relativePath]
            }
            ) {
                edges {
                node {
                    relativePath
                    relativeDirectory
                    name
                    ext
                    id
                    base
                }
            }
            }
        }
    `)

    console.log(data)
    return (
        <div id="work">
            <ol>
                {data.allMarkdownRemark.edges.map((edge) => {
                    return (
                        <li class={edge.node.fields.slug}>
                            <h3>{edge.node.frontmatter.title}</h3>
                            <p>{edge.node.frontmatter.description}</p>
                            {data.allFile.edges.map((edge) => {
                                return (
                                    <img src={`../projects${edge.node.relativeDirectory}/${edge.node.name}-${edge.node.base}${edge.node.ext}`}></img>
                                )
                            })}
                        </li>
                    )
                })}
            </ol>
        </div>
    )
}

export default Work

index.js:

import React from 'react'
import Head from '../components/head'
import Info from '../components/info'
import Work from '../components/work'
import '../styles/index.scss'

const indexPage = () => {
  return (
    <div>
      <Head/>
      <Info/>
      <Work/>
    </div>
  )
}

export default indexPage

回答1:


I should dive deeper in the project to fully understand how you could handle that directly with the graphql query, but a short fix would be to filter out the images not related to the project.

 {data.allFile.edge0s.filter((item) => item.name.includes(edge.node.frontmatter.id).map((edge) => {
    return (
   <img src={`../projects${edge.node.relativeDirectory}/${edge.node.name}-${edge.node.base}${edge.node.ext}`}></img>
)
})}

You will need to add a specific id on the name of your files related to the project so when you fetch them you filter out the one not related.

To be better, you could maybe format your imageSchema and add a specific property to handle the case so you won't need to format the image name and then instead of .includes() you could do item.myProperty === myCustomSchemaProperty.




回答2:


It's much easier than you've tried so far. I would recommend using gatsby-image since all the images belong to the Gatsby ecosystem when you add the following:

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

Gatsby internally will parse everything inside /src/projects/ and will create nodes to make the schema available for GraphQL, so:

{
  allFile(filter: {extension: {eq: "jpg"}}) {
    edges {
      node {
        childImageSharp{
          fluid{
            ...GatsbyImageSharpFluid
          }
        }
      }
    }
  }
}

Then in your component just:

{data.allFile.edges.map((edge) => {
   return <Img fluid={edge.childImageSharp.fluid} />
})}


来源:https://stackoverflow.com/questions/64935654/how-to-use-gatsby-to-display-a-folder-of-images-and-markdown-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!