如何在 Gatsby 中将多个 yaml 文件映射到 frontmatter [英] How to map multiple yaml files to frontmatter in Gatsby

查看:46
本文介绍了如何在 Gatsby 中将多个 yaml 文件映射到 frontmatter的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:

我在将第二个 .yaml 文件映射到 Gatsby 中的第二个 markdown frontmatter 字段时遇到问题.该项目用于杂志,第一个 yaml 文件存储每个作者的详细信息,第二个文件存储每个问题的详细信息.

author.yaml 文件像预期的那样工作,我可以在每个模板和页面上查询它,但 issue.yaml 文件只在两个地方工作:模板,我专门将其数据作为 gatsby 中的页面上下文传递-node,并且(莫名其妙地)用于带有frontmatter特色"字段=== true的降价文件.对于不存在特色"的映射数组,或者当它为假时,每个应该从 issue.yaml 中提取数据的查询都会给出TypeError:无法读取 null 的属性‘id’".

我怀疑这是因为我的 markdown 文件中的 issue 字段不是第一个字段(即作者,并且已经映射到 author.yaml 文件).据我所知,我已经实现了完全相同的两个 yaml 文件.

我尝试过的事情:

我尝试查询我认为应该自动生成的 allAuthorYaml 和 allIssueYaml 节点,但我无法让它们中的任何一个正常工作.我还尝试在 gatsby-node 中创建模式自定义,但我无法弄清楚如何调整教程以定义我需要全局(超出我的头脑)的节点.我在某处读到我可以使用 import YAMLData from "../data/issue.yaml" 直接导入 yaml 数据,然后直接创建一个数组,但它也给了我空/未定义的错误.

我是业余爱好者,根本没有编程背景,这可能是问题的很大一部分.不过,我会很感激任何人可能有的任何帮助.如果有人碰巧发现我的代码需要改进的任何其他地方,一定要告诉我!

我使用的启动器是 https://www.gatsbyjs.org/starters/JugglerX/gatsby-serif-theme/.
我的存储库位于 https://github.com/ljpernic/HQ3.1/tree/总部帮助.

再次感谢!

<小时>

我的 gatsby 配置:

<预><代码>模块.出口 = {站点元数据:{title: '避风港季刊',描述:一本科幻奇幻杂志",提交: {电话:'XXX XXX XXX',电子邮件:'havenquarterly@gmail.com',},菜单链接:[{name: '小说',链接:'/小说',},{name: '非小说',链接:'/非小说',},{name: '来自未来的信',链接:'/未来',},{name: '完整问题',链接:'/fullissues',},{name: '贡献者',链接:'/贡献者',},{name: '关于',链接:'/关于',},{name: '支持',链接:'/支持',},{name: '提交',链接:'/提交',},],},插件: ['盖茨比插件-sass','盖茨比-变压器-json','盖茨比-变压器-备注','盖茨比插件反应头盔',`gatsby-transformer-sharp`,`gatsby-plugin-sharp`,`gatsby-plugin-catch-links`,{解析:'gatsby-source-filesystem',选项: {路径:`${__dirname}/src/pages`,name: '页面',},},/* {解析:'gatsby-source-filesystem',选项: {路径:`${__dirname}/src/posts`,name: '帖子',},},*/{解析:'gatsby-source-filesystem',选项: {路径:`${__dirname}/src/data`,name: '数据',},},{解析:'gatsby-source-filesystem',选项: {路径:`${__dirname}/src/images`,name: '图像',},},{解决:盖茨比变压器备注",选项: {插件: [{解析:`gatsby-remark-images`,选项: {最大宽度:1200,质量:95,},},],},},{解决:'gatsby-plugin-google-analytics',选项: {跟踪ID:指导?指南 : 'UA-XXX-1',//将跟踪脚本放在头部而不是身体头:假的,},},`gatsby-transformer-yaml`,],映射:{//3. 将作者映射到 author.yaml"MarkdownRemark.frontmatter.author": `AuthorYaml`,"MarkdownRemark.frontmatter.issue": `IssueYaml`,},};

我的 gatsby 节点:

const _ = require('lodash');const fs = require("fs")const yaml = require("js-yaml")//从 Markdown 文件创建页面export.createPages = ({ graphql, actions }) =>{const { createPage } = 动作;const ymlDoc = yaml.safeLoad(fs.readFileSync("./src/data/author.yaml", "utf-8"))const ymlIssueDoc = yaml.safeLoad(fs.readFileSync("./src/data/issue.yaml", "utf-8"))返回新的承诺((解决,拒绝)=> {解决(图ql(`询问 {小说档案:allMarkdownRemark(过滤器:{fileAbsolutePath:{正则表达式:/fiction/"}}排序:{字段:[frontmatter___date],顺序:DESC}){边{节点{ID前题{类别精选小路标题日期(格式字符串:DD MMMM YYYY")}摘抄}}}nonfictionarchive: allMarkdownRemark(过滤器:{fileAbsolutePath:{正则表达式:/非小说/"}}排序:{字段:[frontmatter___date],顺序:DESC}){边{节点{ID前题{类别精选小路标题日期(格式字符串:DD MMMM YYYY")}摘抄}}}未来档案:allMarkdownRemark(过滤器:{fileAbsolutePath:{正则表达式:/letters/"}}排序:{字段:[frontmatter___date],顺序:DESC}){边{节点{ID前题{类别精选小路标题日期(格式字符串:DD MMMM YYYY")}摘抄}}}问题存档:allMarkdownRemark(过滤器:{fileAbsolutePath:{正则表达式:/"}}排序:{字段:[frontmatter___date],顺序:DESC}){边{节点{ID前题{类别精选小路标题日期(格式字符串:DD MMMM YYYY")}摘抄}}}作者存档:allMarkdownRemark(过滤器:{fileAbsolutePath:{正则表达式:/"}}排序:{字段:[frontmatter___date],顺序:DESC}){边{节点{ID前题{类别精选小路标题日期(格式字符串:DD MMMM YYYY")}摘抄}}}}`,).then((结果) => {ymlDoc.forEach(元素 => {创建页面({路径:element.idpath,组件:require.resolve("./src/templates/eachauthor.js"),/*创建个人作者页面*/语境: {idname: element.id,生物:element.bio,推特:element.twitter,图片:元素.图片,故事:element.stories,},});});ymlIssueDoc.forEach(element => {创建页面({路径:element.idpath,组件:require.resolve("./src/templates/eachissue.js"),/*creates INDIVIDUAL ISSUE PAGES*/语境: {issueidname: element.id,文字:element.text,currentcover: element.currentcover,艺术家:element.artist,艺术家生物:element.artistbio,艺术家形象:element.artistimage,},});});result.data.fictionarchive.edges.forEach(({ node }) => {const component = path.resolve('src/templates/eachpost.js');/*创建个人小说页面*/创建页面({路径:node.frontmatter.path,成分,语境: {id: node.id,},});});result.data.nonfictionarchive.edges.forEach(({ node }) => {const component = path.resolve('src/templates/eachpost.js');/*创建单独的非小说页面*/创建页面({路径:node.frontmatter.path,成分,语境: {id: node.id,},});});result.data.futurearchive.edges.forEach(({ node }) => {const component = path.resolve('src/templates/eachpost.js');/*创建单个字母页*/创建页面({路径:node.frontmatter.path,成分,语境: {id: node.id,},});});result.data.issuesarchive.edges.forEach(({ node }) => {const component = path.resolve('src/templates/eachpost.js');/*创建个人问题页面;更改模板以更改每个问题页面*/创建页面({路径:node.frontmatter.path,成分,语境: {id: node.id,},});});const FICposts = result.data.fictionarchive.edges/*创建小说列表页面*/const FICpostsPerPage = 10const FICnumPages = Math.ceil(FICposts.length/FICpostsPerPage)Array.from({ length: FICnumPages }).forEach((_, i) => {创建页面({路径:我 === 0 ?`/fiction`:`/fiction/${i + 1}`,组件:path.resolve('src/templates/fictionarchive.js'),语境: {限制:FICpostsPerPage,跳过:我 * FICpostsPerPage,FICnumPages,FICcurrentPage: i + 1,},});});const NONFICposts = result.data.nonfictionarchive.edges/*创建非小说列表页面*/const NONFICpostsPerPage = 10const NONFICnumPages = Math.ceil(NONFICposts.length/NONFICpostsPerPage)Array.from({ length: NONFICnumPages }).forEach((_, i) => {创建页面({路径:我 === 0 ?`/non-fiction` : `/non-fiction/${i + 1}`,组件:path.resolve('src/templates/nonfictionarchive.js'),语境: {限制:非NFICpostsPerPage,跳过:我 * NONFICpostsPerPage,非信息页数,NONFICcurrentPage: i + 1,},});});const FUTposts = result.data.futurearchive.edges/*从未来列表页面创建字母*/const FUTpostsPerPage = 10const FUTnumPages = Math.ceil(FUTposts.length/FUTpostsPerPage)Array.from({ length: FUTnumPages }).forEach((_, i) => {创建页面({路径:我 === 0 ?`/future`:`/future/${i + 1}`,组件:path.resolve('src/templates/futurearchive.js'),语境: {限制:FUTpostsPerPage,跳过:我 * FUTpostsPerPage,FUTnumPages,FUTcurrentPage: i + 1,},});});const FULLposts = result.data.issuesarchive.edges/*创建问题列表页面*/const FULLpostsPerPage = 10const FULLnumPages = Math.ceil(FULLposts.length/FULLpostsPerPage)Array.from({ length: FULLnumPages }).forEach((_, i) => {创建页面({路径:我 === 0 ?`/fullissues`:`/fullissues/${i + 1}`,组件:path.resolve('src/templates/issuesarchive.js'),语境: {限制:FULLpostsPerPage,跳过:我 * FULLpostsPerPage,FULLnumPages,FULLcurrentPage: i + 1,},});});const AUTposts = result.data.authorarchive.edgesconst AUTpostsPerPage = 10const AUTnumPages = Math.ceil(AUTposts.length/AUTpostsPerPage)Array.from({ length: AUTnumPages }).forEach((_, i) => {创建页面({路径:i === 0 ?`/contributors`:`/contributors/${i + 1}`,组件:path.resolve('src/templates/authorarchive.js'),语境: {限制:AUTpostsPerPage,跳过:i * AUTpostsPerPage,AUTnumPages,AUTcurrentPage: i + 1,},});});解决();}),);});};

我的首页(缩短):

import { graphql, withPrefix, Link } from 'gatsby';从gatsby-image"导入图像;从反应头盔"导入头盔;从 '../components/SEO' 导入 SEO;从'../layouts/index'导入布局;const Home = (props) =>{//这是头版,包括精选故事、最新故事和最新问题const json = props.data.allFeaturesJson.edges;const posts = props.data.allMarkdownRemark.edges;返回 (<Layout bodyClass="page-home"><SEO title="首页"/><头盔><元名称=避风港季刊"content="一本科幻奇幻杂志"/></头盔>{/*特色*/}<div className="intro pb-1"><div className="容器"><div className="row2 justify-content-start"><div className="grid-container pt-2"><div className="宽"><div className="col-12"><链接到="/精选"><h4>专题故事</h4></链接><小时/>

{帖子.filter(post => post.node.frontmatter.featured === true)/*这里只查看带有featured:true的md文件*/.map(({ node: post }) => {返回 (<div className="container" key={post.id}><h1pb><Link to={post.frontmatter.path}>{post.frontmatter.title}</Link><h2>通过<链接到={post.frontmatter.author.idpath}>{post.frontmatter.author.id}</Link>在 <Link to={post.frontmatter.issue.idpath}>{post.frontmatter.issue.id}</Link></h2>/*这是这个页面上唯一一个问题 YAML 数组似乎可以工作的地方.它仅在精选时有效 === 真,这太疯狂了*/<p>{post.excerpt}</p>

)})}

<div className="thin">{帖子.filter(post => post.node.frontmatter.featured === true)/*这里只查看带有featured:true的md文件*/.map(({ node: post }) => {返回 (<链接到="/最新"><图像类名="topimage"fixed={post.frontmatter.currentcover.childImageSharp.fixed}/*这从md文件中提取图像,特征为:true(当前封面)*//></链接>)})}

<小时/><div className="col-12">{帖子.filter(post => !post.node.frontmatter.featured).filter(post => post.node.frontmatter.issue === "Issue One Summer 2020")/*这应该只过滤具有问题的 MD 文件:Issue One Summer 2020"*/.slice(0, 6).map(({ node: post }) => {返回 (<div className="postbody" key={post.id}><h2pb><Link to={post.frontmatter.path}>{post.frontmatter.title}</Link>通过 {post.frontmatter.author.id}</Link>({post.frontmatter.category})

)})}

<小时/>

<div className="postbody"><div className="容器 pt-8 pt-md-4"><div className="row2 justify-content-start pt-2"><div className="col-12"><链接到="/小说"><h4>最新小说</h4></链接><小时/>

{/*小说*/}<div className="容器">{帖子.filter(post => !post.node.frontmatter.featured).filter(post => post.node.frontmatter.category === "fiction")/*这应该只从类别为fiction"的md文件中提取,不包括标记为特色的帖子*/.slice(0, 6).map(({ node: post }) => {返回 (<div className="container" key={post.id}><Image className="inlineimage"流体={post.frontmatter.cover.childImageSharp.fluid}/*这应该从类别为小说"的md文件中提取图像*//><h1pb><Link to={post.frontmatter.path}>{post.frontmatter.title}</Link><h2>通过<链接到={post.frontmatter.author.idpath}>{post.frontmatter.author.id}</Link>在 <Link to={post.frontmatter.issue}>{post.frontmatter.issue}</Link></h2><p>{post.excerpt}</p><小时/>

)})}<div className="col-12 text-center pb-3"><Link className="button button-primary" to="/fiction">查看所有故事</链接>

</布局>);};导出 const 查询 = graphql`询问 {allAuthorYaml {节点{生物ID身份路径图片 {childImageSharp {固定(宽度:200){... GatsbyImageSharpFixed}流体(最大宽度:150,最大高度:150){... GatsbyImageSharpFluid}}}故事{物品}推特}}allIssueYaml {边{节点{艺术家艺术家生物ID身份路径文本艺术家形象{childImageSharp {固定(宽度:200){... GatsbyImageSharpFixed}流体(最大宽度:150,最大高度:150){... GatsbyImageSharpFluid}}}当前覆盖{childImageSharp {固定(宽度:403){... GatsbyImageSharpFixed}流体(最大宽度:300,最大高度:300){... GatsbyImageSharpFluid}}}}}}allMarkdown备注(过滤器:{fileAbsolutePath:{正则表达式:/.*.md$/"}}排序:{字段:[frontmatter___date],顺序:DESC}){总数边{节点{ID前题{精选小路标题作者 {ID身份路径生物推特图片 {childImageSharp {固定(宽度:200){... GatsbyImageSharpFixed}流体(最大宽度:150,最大高度:150){... GatsbyImageSharpFluid}}}}问题 {ID身份路径当前覆盖{childImageSharp {固定(宽度:403){... GatsbyImageSharpFixed}流体(最大宽度:300){... GatsbyImageSharpFluid}}}文本艺术家艺术家形象{childImageSharp {固定(宽度:200){... GatsbyImageSharpFixed}流体(最大宽度:150,最大高度:150){... GatsbyImageSharpFluid}}}艺术家生物}日期(格式字符串:DD MMMM YYYY")类别当前覆盖{childImageSharp {固定(宽度:403){... GatsbyImageSharpFixed}流体(最大宽度:300){... GatsbyImageSharpFluid}}}覆盖 {childImageSharp {固定(宽度:403){... GatsbyImageSharpFixed}流体(最大宽度:300){... GatsbyImageSharpFluid}}}}摘录(修剪长度:650)}}}allFeaturesJson {边{节点{ID标题描述图片}}}}`;导出默认首页;

一个典型的带有损坏数组的模板:

import { graphql, Link, withPrefix } from 'gatsby';从 '../components/SEO' 导入 SEO;从'../layouts/index'导入布局;从反应头盔"导入头盔;从 'gatsby-image' 导入图像;导出默认类 Fictionarchive 扩展 React.Component {使成为() {const posts = this.props.data.allMarkdownRemark.edgesconst json = this.props.data.allFeaturesJson.edges;const { FICcurrentPage, FICnumPages } = this.props.pageContextconst isFirst = FICcurrentPage === 1const isLast = FICcurrentPage === FICnumPagesconst prevPage = FICcurrentPage - 1 === 1 ?/":`/fiction/${FICcurrentPage - 1}`const nextPage = `/fiction/${FICcurrentPage + 1}`返回 (<Layout bodyClass="page-home"><SEO title="小说"/><头盔><元名称=说明"content="Haven Quarterly 的所有小说"/></头盔><div className="postbody"><div className="container pt-md-5"><div className="row2 justify-content-start"><div className="col-12"><h3>最新小说</h3><小时/>

<div className="容器">{帖子.filter(post => post.node.frontmatter.category === "小说").map(({ node: post }) => {返回 (<div className="container" key={post.id}><Image className="inlineimage"流体={post.frontmatter.cover.childImageSharp.fluid}/><h1pb><Link to={post.frontmatter.path}>{post.frontmatter.title}</Link><h2>通过<链接到={post.frontmatter.author.idpath}>{post.frontmatter.author.id}</Link>在 <Link to={post.frontmatter.issue.idpath}>{post.frontmatter.issue.id}</Link></h2><p>{post.excerpt}</p><小时/>

)})}<div className="容器"><div className="row"><div className="col-sm"><p className="text-left">{!isFirst &&(<链接到={prevPage} rel="prev">← 上一页</链接>)}</p>

</布局>)}}导出 constictionarchiveQuery = graphql`查询虚构档案查询($skip:Int!,$limit:Int!){allMarkdown备注(过滤器:{frontmatter:{category:{eq:"fiction"} } }排序:{字段:[frontmatter___date],顺序:DESC}限制:$limit跳过:$skip){边{节点{摘录(修剪长度:750)前题{类别精选小路标题作者 {ID身份路径生物推特图片 {childImageSharp {固定(宽度:400){... GatsbyImageSharpFixed}流体(最大宽度:400,最大高度:400){... GatsbyImageSharpFluid}}}}问题 {ID身份路径当前覆盖{childImageSharp {固定(宽度:403){... GatsbyImageSharpFixed}流体(最大宽度:300){... GatsbyImageSharpFluid}}}文本艺术家艺术家形象{childImageSharp {固定(宽度:200){... GatsbyImageSharpFixed}流体(最大宽度:150,最大高度:150){... GatsbyImageSharpFluid}}}艺术家生物}日期(格式字符串:DD MMMM YYYY")覆盖 {childImageSharp {固定(宽度:322){... GatsbyImageSharpFixed}流体(最大宽度:450){... GatsbyImageSharpFluid}}}}html}}}allFeaturesJson {边{节点{ID标题描述图片}}}}`

解决方案

解决方案

比我更聪明,并确保您已在 yaml 文件中实际定义了 Markdown 文件中的所有值.

更长的解释

我在 Gatsby 的 GitHub 存储库上询问,结果证明解决方案非常简单:

一切都或多或少地设置正确.问题是在我的第二个 yaml 文件中,我没有定义我在 Markdown 文件中列出的所有值.因此,在 30 多个 .md 文件之间,问题字段总共有四个值,但在我的 issue.yaml 文件中,我只定义了其中的两个.它返回了一个空错误,因为当它循环遍历 Markdown 文件时,它说:我有第三个值,但在 yaml 文件中没有与它对应的值."

回答我问题的人说有两种解决方案:

<块引用>

  1. 在 issue.yaml 中定义所有问题 ID,以便您至少获得 id返回
  2. 在帖子的前端定义一个替代问题标题并检查问题是否返回空值.如果是,请隐藏您的组件并改用 issueTitle

我认为这并不重要,因为我认为我只是从带有我定义的字段的降价文件中调用数据(换句话说,我认为我已经排除了那些我没有在我的文件中定义的 .md 文件)yaml),但这是错误的.

其他注意事项

另外两个让我感到困惑的简单问题: 1. 确保 yaml 文件中定义的内容与 markdown 文件的相应字段中提供的内容之间的拼写完全相同.2. 确保您使用 id 字段,根据 此建议,在映射您的yaml 文件到 frontmatter 字段.

最后的想法

结果我不知道我在做什么.但我希望这个答案能帮助其他任何与 Gatsby 纠缠在同一问题上的人.

链接到 LekoArts 提供的更完整的答案:https://github.com/gatsbyjs/gatsby/issues/25373

The problem:

I am having trouble mapping a second .yaml file to a second markdown frontmatter field in Gatsby. The project is for a magazine, with the first yaml file storing details about each author and the second file storing details about each issue.

The author.yaml file worked like it was supposed to, and I can query it across every template and page, but the issue.yaml file only works in two places: templates where I specifically passed its data as page context in gatsby-node, and (inexplicably) for markdown files with the frontmatter "featured" field === true. For mapped arrays in which "featured" is not present, or when it's false, every query that should pull data from the issue.yaml gives "TypeError: Cannot read property 'id' of null."

My suspicion is that it's because the issue field on my markdown files isn't the first field (which is author, and already mapped to the author.yaml file). As far as I can tell, I've implemented both yaml files exactly the same.

Things I've tried:

I've tried to query the allAuthorYaml and allIssueYaml nodes that I think are supposed to be automatically generated, but I couldn't get either of them to work. I also tried to create a schema customization in gatsby-node, but I couldn't figure out how to adapt the tutorial to define the nodes I needed globally (way over my head). I read somewhere that I could import the yaml data directly with import YAMLData from "../data/issue.yaml" and then create an array directly, but it also gave me null/undefined errors.

I am a hobbyist, and don't have a background in programming at all, which is probably a big part of the problem. Still, I'd be grateful for any help anyone might have. And if anyone happens to spot any other places my code needs improving, definitely let me know!

The starter I used was https://www.gatsbyjs.org/starters/JugglerX/gatsby-serif-theme/.
My repository is at https://github.com/ljpernic/HQ3.1/tree/HQhelp.

Thanks again!


My gatsby-config:


module.exports = {
  siteMetadata: {
    title: 'Haven Quarterly',
    description: 'a magazine of science fiction and fantasy',
    submit: {
      phone: 'XXX XXX XXX',
      email: 'havenquarterly@gmail.com',
    },
    menuLinks: [
      {
        name: 'Fiction',
        link: '/fiction',
      },
      {
        name: 'Non-fiction',
        link: '/non-fiction',
      },
      {
        name: 'Letters from the Future',
        link: '/future',
      },
      {
        name: 'Full Issues',
        link: '/fullissues',
      },
      {
        name: 'Contributors',
        link: '/contributors',
      },
      {
        name: 'About',
        link: '/about',
      },
      {
        name: 'Support',
        link: '/support',
      },
      {
        name: 'Submit',
        link: '/submit',
      },
    ],
  },
  plugins: [
    'gatsby-plugin-sass',
    'gatsby-transformer-json',
    'gatsby-transformer-remark',
    'gatsby-plugin-react-helmet',
    `gatsby-transformer-sharp`, 
    `gatsby-plugin-sharp`,
    `gatsby-plugin-catch-links`,
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/src/pages`,
        name: 'pages',
      },
    },
/*    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/src/posts`,
        name: 'posts',
      },
    },*/
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/src/data`,
        name: 'data',
      },
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/src/images`,
        name: 'images',
      },
    },
    {
      resolve: "gatsby-transformer-remark",
      options: {
        plugins: [
          {
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 1200,
              quality: 95, 
            },
          },
        ], 
      },
    },
    {
      resolve: 'gatsby-plugin-google-analytics',
      options: {
        trackingId: guid ? guid : 'UA-XXX-1',
        // Puts tracking script in the head instead of the body
        head: false,
      },
    },
  `gatsby-transformer-yaml`,
  ],
  mapping: {
    // 3. map author to author.yaml
    "MarkdownRemark.frontmatter.author": `AuthorYaml`,
    "MarkdownRemark.frontmatter.issue": `IssueYaml`,
  },
};

My gatsby-node:

const _ = require('lodash');
const fs = require("fs")
const yaml = require("js-yaml")

// Create pages from markdown files
exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions;
  const ymlDoc = yaml.safeLoad(fs.readFileSync("./src/data/author.yaml", "utf-8"))
  const ymlIssueDoc = yaml.safeLoad(fs.readFileSync("./src/data/issue.yaml", "utf-8"))
  return new Promise((resolve, reject) => {
    resolve(
      graphql(
        `
          query {
            fictionarchive: allMarkdownRemark(
              filter: { fileAbsolutePath: { regex: "/fiction/" } }
              sort: { fields: [frontmatter___date], order: DESC }
            ) {
              edges {
                node {
                  id
                  frontmatter {
                    category
                    featured
                    path
                    title
                    date(formatString: "DD MMMM YYYY")
                  }
                  excerpt
                }
              }
            }

            nonfictionarchive: allMarkdownRemark(
              filter: { fileAbsolutePath: { regex: "/non-fiction/" } }
              sort: { fields: [frontmatter___date], order: DESC }
            ) {
              edges {
                node {
                  id
                  frontmatter {
                    category
                    featured
                    path
                    title
                    date(formatString: "DD MMMM YYYY")
                  }
                  excerpt
                }
              }
            }

            futurearchive: allMarkdownRemark(
              filter: { fileAbsolutePath: { regex: "/letters/" } }
              sort: { fields: [frontmatter___date], order: DESC }
            ) {
              edges {
                node {
                  id
                  frontmatter {
                    category
                    featured
                    path
                    title
                    date(formatString: "DD MMMM YYYY")
                  }
                  excerpt
                }
              }
            }

            issuesarchive: allMarkdownRemark(
              filter: { fileAbsolutePath: { regex: "/" } }
              sort: { fields: [frontmatter___date], order: DESC }
            ) {
              edges {
                node {
                  id
                  frontmatter {
                    category
                    featured
                    path
                    title
                    date(formatString: "DD MMMM YYYY")
                  }
                  excerpt
                }
              }
            }

            authorarchive: allMarkdownRemark(
              filter: { fileAbsolutePath: { regex: "/" } }
              sort: { fields: [frontmatter___date], order: DESC }
            ) {
              edges {
                node {
                  id
                  frontmatter {
                    category
                    featured
                    path
                    title
                    date(formatString: "DD MMMM YYYY")
                  }
                  excerpt
                }
              }
            }

          }
        `,
      ).then((result) => {
        ymlDoc.forEach(element => {
          createPage({
            path: element.idpath,
            component: require.resolve("./src/templates/eachauthor.js"),                     /*creates INDIVIDUAL AUTHOR PAGES*/
            context: {
              idname: element.id,
              bio: element.bio,
              twitter: element.twitter,
              picture: element.picture,
              stories: element.stories,
            },
          });
        });
        ymlIssueDoc.forEach(element => {
          createPage({
            path: element.idpath,
            component: require.resolve("./src/templates/eachissue.js"),                      /*creates INDIVIDUAL ISSUE PAGES*/
            context: {
              issueidname: element.id,
              text: element.text,
              currentcover: element.currentcover,
              artist: element.artist,
              artistbio: element.artistbio,
              artistimage: element.artistimage,
            },
          });
        });
        result.data.fictionarchive.edges.forEach(({ node }) => {
          const component = path.resolve('src/templates/eachpost.js');                      /*creates INDIVIDUAL FICTION PAGES*/
          createPage({
            path: node.frontmatter.path,
            component,
            context: {
              id: node.id,
            },
          });
        });
        result.data.nonfictionarchive.edges.forEach(({ node }) => {
          const component = path.resolve('src/templates/eachpost.js');                      /*creates INDIVIDUAL NON-FICTION PAGES*/
        createPage({
          path: node.frontmatter.path,
          component,
          context: {
            id: node.id,
          },
        });
      });
        result.data.futurearchive.edges.forEach(({ node }) => {
          const component = path.resolve('src/templates/eachpost.js');                      /*creates INDIVIDUAL LETTER PAGES*/
          createPage({
            path: node.frontmatter.path,
            component,
            context: {
              id: node.id,
            },
          });
        });
        result.data.issuesarchive.edges.forEach(({ node }) => {
          const component = path.resolve('src/templates/eachpost.js');                      /*creates INDIVIDUAL ISSUE PAGES; change template to change every issue page*/
          createPage({
            path: node.frontmatter.path,
            component,
            context: {
              id: node.id,
            },
          });
        });
        const FICposts = result.data.fictionarchive.edges                                   /*creates FICTION LIST PAGES*/
        const FICpostsPerPage = 10
        const FICnumPages = Math.ceil(FICposts.length / FICpostsPerPage)
        Array.from({ length: FICnumPages }).forEach((_, i) => {
          createPage({
            path: i === 0 ? `/fiction` : `/fiction/${i + 1}`,
            component: path.resolve('src/templates/fictionarchive.js'),
            context: {
              limit: FICpostsPerPage,
              skip: i * FICpostsPerPage,
              FICnumPages,
              FICcurrentPage: i + 1,
            },
          });
        });
        const NONFICposts = result.data.nonfictionarchive.edges                             /*creates NON-FICTION LIST PAGES*/
        const NONFICpostsPerPage = 10
        const NONFICnumPages = Math.ceil(NONFICposts.length / NONFICpostsPerPage)
        Array.from({ length: NONFICnumPages }).forEach((_, i) => {
          createPage({
            path: i === 0 ? `/non-fiction` : `/non-fiction/${i + 1}`,
            component: path.resolve('src/templates/nonfictionarchive.js'),
            context: {
              limit: NONFICpostsPerPage,
              skip: i * NONFICpostsPerPage,
              NONFICnumPages,
              NONFICcurrentPage: i + 1,
            },
          });
        });
        const FUTposts = result.data.futurearchive.edges                                   /*creates LETTERS FROM THE FUTURE LIST PAGES*/
        const FUTpostsPerPage = 10
        const FUTnumPages = Math.ceil(FUTposts.length / FUTpostsPerPage)
        Array.from({ length: FUTnumPages }).forEach((_, i) => {
          createPage({
            path: i === 0 ? `/future` : `/future/${i + 1}`,
            component: path.resolve('src/templates/futurearchive.js'),
            context: {
              limit: FUTpostsPerPage,
              skip: i * FUTpostsPerPage,
              FUTnumPages,
              FUTcurrentPage: i + 1,
            },
          });
        });
        const FULLposts = result.data.issuesarchive.edges                                   /*creates ISSUES LIST PAGES*/
        const FULLpostsPerPage = 10
        const FULLnumPages = Math.ceil(FULLposts.length / FULLpostsPerPage)
        Array.from({ length: FULLnumPages }).forEach((_, i) => {
          createPage({
            path: i === 0 ? `/fullissues` : `/fullissues/${i + 1}`,
            component: path.resolve('src/templates/issuesarchive.js'),
            context: {
              limit: FULLpostsPerPage,
              skip: i * FULLpostsPerPage,
              FULLnumPages,
              FULLcurrentPage: i + 1,
            },
          });
        });
        const AUTposts = result.data.authorarchive.edges
        const AUTpostsPerPage = 10
        const AUTnumPages = Math.ceil(AUTposts.length / AUTpostsPerPage)
        Array.from({ length: AUTnumPages }).forEach((_, i) => {
          createPage({
            path: i === 0 ? `/contributors` : `/contributors/${i + 1}`,
            component: path.resolve('src/templates/authorarchive.js'),
            context: {
              limit: AUTpostsPerPage,
              skip: i * AUTpostsPerPage,
              AUTnumPages,
              AUTcurrentPage: i + 1,
            },
          });
        });
        resolve();
      }),
    );
  });
};

My front page (shortened):

import { graphql, withPrefix, Link } from 'gatsby';
import Image from "gatsby-image";
import Helmet from 'react-helmet';
import SEO from '../components/SEO';
import Layout from '../layouts/index';

const Home = (props) => {                                                     //THIS SETS THE FRONT PAGE, including featured story, latest stories, and latest issues
  const json = props.data.allFeaturesJson.edges;
  const posts = props.data.allMarkdownRemark.edges;

  return (
    <Layout bodyClass="page-home">
      <SEO title="Home" />
      <Helmet>
        <meta
          name="Haven Quarterly"
          content="A Magazine of Science Fiction and Fantasy"
        />
      </Helmet>

                                                                                          {/*FEATURED*/}
      <div className="intro pb-1">
        <div className="container">
          <div className="row2 justify-content-start">
            <div className="grid-container pt-2">
              <div className="wide">
                <div className="col-12">
                  <Link to="/featured">
                      <h4>Featured Story</h4>
                  </Link>
                  <hr />
                </div>
                {posts
                  .filter(post => post.node.frontmatter.featured === true)                       /*This looks at only the md file with featured: true*/
                  .map(({ node: post }) => {
                    return (
                      <div className="container" key={post.id}>
                        <h1 pb>
                          <Link to={post.frontmatter.path}>{post.frontmatter.title}</Link>
                        </h1>
                        <h2>By <Link to={post.frontmatter.author.idpath}> {post.frontmatter.author.id}</Link> in <Link to={post.frontmatter.issue.idpath}> {post.frontmatter.issue.id}</Link></h2>          /*THIS IS THE ONLY PLACE ON THIS PAGE WHERE THE ISSUE YAML ARRAY SEEMS TO WORK. IT ONLY WORKS WHEN featured === true WHICH IS CRAZY*/
                        <p>{post.excerpt}</p>
                      </div>
                      )
                    })}
              </div>      
              <div className="thin">
              {posts
                  .filter(post => post.node.frontmatter.featured === true)                     /*This looks at only the md file with featured: true*/
                  .map(({ node: post }) => {
                    return (

                      <Link to="/latest">
                        <Image className="topimage"
                          fixed={post.frontmatter.currentcover.childImageSharp.fixed}      /*This pulls the image from the md file with featured: true (current cover)*/
                        />
                      </Link>

                      )
                    })}
              </div>
            </div>
            <hr />

            <div className="col-12">
              {posts
              .filter(post => !post.node.frontmatter.featured)
              .filter(post => post.node.frontmatter.issue === "Issue One Summer 2020")          /*THIS SHOULD FILTER ONLY MD FILES WITH issue: Issue One Summer 2020"*/
              .slice(0, 6)
              .map(({ node: post }) => {
                return (
                  <div className="postbody" key={post.id}>

                      <h2 pb>
                        <Link to={post.frontmatter.path}>{post.frontmatter.title}</Link> by <Link to={post.frontmatter.author.idpath}> {post.frontmatter.author.id}</Link> ({post.frontmatter.category})
                      </h2>
                  </div>
                )
              })}
            </div>

            <hr />

          </div>
        </div>
      </div>


    <div className="postbody">
      <div className="container pt-8 pt-md-4">
        <div className="row2 justify-content-start pt-2">
          <div className="col-12">
            <Link to="/fiction">
                <h4>Latest Fiction</h4>
            </Link>
            <hr />
          </div>
                                                                                      {/*FICTION*/}
          <div className="container">

            {posts
              .filter(post => !post.node.frontmatter.featured)
              .filter(post => post.node.frontmatter.category === "fiction")          /*This should only pull from md files with category "fiction", excluding posts marked featured*/
              .slice(0, 6)
              .map(({ node: post }) => {
                return (
                  <div className="container" key={post.id}>
                      <Image className="inlineimage"
                        fluid={post.frontmatter.cover.childImageSharp.fluid}          /*This should pull image from md files with category "fiction"*/
                      />
                      <h1 pb>
                        <Link to={post.frontmatter.path}>{post.frontmatter.title}</Link>
                      </h1>
                      <h2>By <Link to={post.frontmatter.author.idpath}> {post.frontmatter.author.id}</Link> in  <Link to={post.frontmatter.issue}> {post.frontmatter.issue}</Link></h2>
                      <p>{post.excerpt}</p>
                      <hr />
                  </div>
                )
              })}
            <div className="col-12 text-center pb-3">
              <Link className="button button-primary" to="/fiction">
                View All Stories
              </Link>
            </div>
          </div>
        </div>
      </div>
    </div>          
    </Layout>
  );
};

export const query = graphql`
  query {
    allAuthorYaml {
      nodes {
        bio
        id
        idpath
        picture {
          childImageSharp {
            fixed(width: 200) {
              ...GatsbyImageSharpFixed 
            }
            fluid(maxWidth: 150, maxHeight: 150) {
              ...GatsbyImageSharpFluid
            }
          }
        }
        stories {
          item
        }
        twitter
      }
    }
    allIssueYaml {
      edges {
        node {
          artist
          artistbio
          id
          idpath
          text
          artistimage {
            childImageSharp {
              fixed(width: 200) {
                ...GatsbyImageSharpFixed 
              }
              fluid(maxWidth: 150, maxHeight: 150) {
                ...GatsbyImageSharpFluid
              }
            }
          }
          currentcover {
            childImageSharp {
              fixed(width: 403) {
                ...GatsbyImageSharpFixed 
              }
              fluid(maxWidth: 300, maxHeight: 300) {
                ...GatsbyImageSharpFluid
              }
            }
          }
        }
      }
    }
    allMarkdownRemark(
      filter: { fileAbsolutePath: { regex: "/.*.md$/" }}
      sort: { fields: [frontmatter___date], order: DESC }
      ) {
      totalCount
      edges {
        node {
          id
          frontmatter {
            featured
            path
            title
            author {
              id
              idpath
              bio
              twitter
              picture {
                childImageSharp {
                  fixed(width: 200) {
                    ...GatsbyImageSharpFixed 
                  }
                  fluid(maxWidth: 150, maxHeight: 150) {
                    ...GatsbyImageSharpFluid
                  }
                }
              }
            }
            issue {
              id
              idpath
              currentcover {
                childImageSharp {
                  fixed(width: 403) {
                    ...GatsbyImageSharpFixed 
                  }
                  fluid(maxWidth: 300) {
                    ...GatsbyImageSharpFluid
                  }
                }
              }
              text
              artist
              artistimage {
                childImageSharp {
                  fixed(width: 200) {
                    ...GatsbyImageSharpFixed 
                  }
                  fluid(maxWidth: 150, maxHeight: 150) {
                    ...GatsbyImageSharpFluid
                  }
                }
              }
              artistbio 
            }
            date(formatString: "DD MMMM YYYY")
            category
            currentcover {
              childImageSharp {
                fixed(width: 403) {
                  ...GatsbyImageSharpFixed 
                }
                fluid(maxWidth: 300) {
                  ...GatsbyImageSharpFluid
                }
              }
            }
            cover {
              childImageSharp {
                fixed(width: 403) {
                  ...GatsbyImageSharpFixed 
                }
                fluid(maxWidth: 300) {
                  ...GatsbyImageSharpFluid
                }
              }
            }            
          }
          excerpt(pruneLength: 650)
        }
      }
    }
    allFeaturesJson {
      edges {
        node {
          id
          title
          description
          image
        }
      }
    }
  }
`;

export default Home;

A typical template with broken array:

import { graphql, Link, withPrefix } from 'gatsby';
import SEO from '../components/SEO';
import Layout from '../layouts/index';
import Helmet from 'react-helmet';
import Image from 'gatsby-image';

export default class Fictionarchive extends React.Component {
  render() {
    const posts = this.props.data.allMarkdownRemark.edges
    const json = this.props.data.allFeaturesJson.edges;

    const { FICcurrentPage, FICnumPages } = this.props.pageContext
    const isFirst = FICcurrentPage === 1
    const isLast = FICcurrentPage === FICnumPages
    const prevPage = FICcurrentPage - 1 === 1 ? "/" : `/fiction/${FICcurrentPage - 1}`
    const nextPage = `/fiction/${FICcurrentPage + 1}`

    return (
      <Layout bodyClass="page-home">
      <SEO title="Fiction" />
      <Helmet>
        <meta
          name="description"
          content="all fiction of Haven Quarterly"
        />
      </Helmet>

    <div className="postbody">
      <div className="container pt-md-5">
        <div className="row2 justify-content-start">
          <div className="col-12">
                <h3>Latest Fiction</h3>
            <hr />
          </div>

          <div className="container">
          {posts
              .filter(post => post.node.frontmatter.category === "fiction")
              .map(({ node: post }) => {
                return (
                  <div className="container" key={post.id}>
                      <Image className="inlineimage"
                        fluid={post.frontmatter.cover.childImageSharp.fluid}
                      />
                      <h1 pb>
                        <Link to={post.frontmatter.path}>{post.frontmatter.title}</Link>
                      </h1>
                      <h2>By <Link to={post.frontmatter.author.idpath}> {post.frontmatter.author.id}</Link> in  <Link to={post.frontmatter.issue.idpath}> {post.frontmatter.issue.id}</Link></h2>
                      <p>{post.excerpt}</p>
                      <hr />
                  </div>
                )
              })}
              <div className="container">
                <div className="row">
                  <div className="col-sm">
                    <p className="text-left">
                      {!isFirst && (
                        <Link to={prevPage} rel="prev">
                          ← Previous Page
                        </Link>
                      )}
                    </p>
                  </div>            
                </div>         
              </div>
          </div>
        </div>
      </div>
    </div>


    </Layout>
    )
  }
}

export const fictionarchiveQuery = graphql`
  query fictionarchiveQuery($skip: Int!, $limit: Int!) {
    allMarkdownRemark(
      filter: { frontmatter: {category:{eq:"fiction"} } }
      sort: { fields: [frontmatter___date], order: DESC }
      limit: $limit
      skip: $skip
    ) {
      edges {
        node {
          excerpt(pruneLength: 750)    
          frontmatter {
            category
            featured
            path
            title
            author {
              id
              idpath
              bio
              twitter
              picture {
                childImageSharp {
                  fixed(width: 400) {                                           
                    ...GatsbyImageSharpFixed 
                  }
                  fluid(maxWidth: 400, maxHeight: 400) {
                    ...GatsbyImageSharpFluid
                  }
                }
              }
            }
            issue {
              id
              idpath
              currentcover {
                childImageSharp {
                  fixed(width: 403) {
                    ...GatsbyImageSharpFixed 
                  }
                  fluid(maxWidth: 300) {
                    ...GatsbyImageSharpFluid
                  }
                }
              }
              text
              artist
              artistimage {
                childImageSharp {
                  fixed(width: 200) {
                    ...GatsbyImageSharpFixed 
                  }
                  fluid(maxWidth: 150, maxHeight: 150) {
                    ...GatsbyImageSharpFluid
                  }
                }
              }
              artistbio 
            }
            date(formatString: "DD MMMM YYYY")
            cover {
              childImageSharp {
                fixed(width: 322) {
                  ...GatsbyImageSharpFixed 
                }
                fluid(maxWidth: 450) {
                  ...GatsbyImageSharpFluid
                }
              }
            }
          }
          html
        }
      }
    }
    allFeaturesJson {
      edges {
        node {
          id
          title
          description
          image
        }
      }
    }
  }
`

解决方案

Solution

Be smarter than me and make sure you've actually defined all of the values you have in your markdown files in your yaml file.

Longer Explanation

I asked on the GitHub repository for Gatsby, and the solution turned out to be really easy:

Everything was set up more or less correctly. The problem turned out to be that in my second yaml file, I wasn't defining all of the values that I was listing in my markdown files. So, between the 30+ .md files, I had four values total for the issue field, but in my issue.yaml file, I was only defining two of them. It returned a null error because when it cycled through the markdown files, it said, "I have this third value, but nothing that corresponds to it in the yaml file."

The person who answered my question said there were two solutions:

  1. Define all issue IDs in issue.yaml so that you get at least the id back
  2. Define an alternative issueTitle in your frontmatter of the posts and check whether issue returns null. If yes, hide your components and use issueTitle instead

I thought this didn't matter because I thought I was only calling data from markdown files with the fields I had defined (in other words, I thought I was already excluding those .md files that I hadn't defined in my yaml), but that was erroneous.

Other Things to Note

Two other simple issues that tripped me up: 1. Make sure that the spelling is exactly the same between what's defined in the yaml file and what is provided in the corresponding field of the markdown file. 2. Make sure you use an id field, as per this suggestion, when mapping your yaml file to a frontmatter field.

Final Thoughts

Turns out I don't know what I'm doing. But I hope that this answer helps anyone else noodling around with Gatsby who gets stuck on the same problem.

Link to the fuller answer kindly provided by LekoArts: https://github.com/gatsbyjs/gatsby/issues/25373

这篇关于如何在 Gatsby 中将多个 yaml 文件映射到 frontmatter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆