【问题标题】:Handle empty strings as image paths when using gatsby-transformer-sharp使用 gatsby-transformer-sharp 时将空字符串作为图像路径处理
【发布时间】:2019-06-14 23:07:49
【问题描述】:

我正在使用带有 Netlify CMS 的 Gatsby。我使用 gatsby-transformer-sharp 进行各种图像处理。

在 Netlify CMS 中,如果用户删除图片,frontmatter 值会变为空字符串,例如:

my-blog-post.md:

---
image: ''
---

当我查询 Graphql 时,这会导致 gatsby-transformer-sharp 出错:

Error Field "image" must not have a selection since type "String" has no subfields.

这似乎是因为 Gatsby/Graphql 已将图像字段推断为字符串。

所以我创建了一个schema.md 文件,所以总会有至少一个带有有效图像的条目:

_schema.md:

---
image: /some-dummy-image.jpg
---

这似乎部分解决了问题 - 构建只是偶尔失败。但它确实仍然失败。我认为它必须从它遇到的第一个降价文件中推断出它的架构——有时它首先找到_schema.md,有时它首先找到my-blog-post.md

有没有人设法解决这个问题?

【问题讨论】:

  • 目前还没有,但似乎有什么事情要发生了——现在每个人都在使用隐藏的虚拟帖子(在查询中被过滤掉了)...you can see the discussion here
  • 谢谢 - 我已经在使用 'dummy post' 方法(我称之为 _schema.md)。问题是这有时会失败。有时 Gatsby 会错误地将image 字段推断为字符串(因为my-blog-post.md 包含image: '')。我不确定 Gatsby 在推断架构时如何决定要使用的 which 文件。我在我的虚拟帖子文件名中添加了一个下划线,这样当从文件系统读取时它会按字母顺序排在第一位,但它并不总是有效。

标签: gatsby


【解决方案1】:

更新

自 Gatsby@^2.2.0 以来,处理此错误的最佳方法是使用 Gatsby 挂钩 createSchemaCustomization。我们需要告诉 Gatsby image 字段肯定是一个文件。

exports.createSchemaCustomization = ({ actions }) => {
  actions.createType(`
    type RemarkFrontmatter @infer {
      image: File
    }

    type MarkdownRemark implements Node @infer {
      frontmatter: RemarkFrontmatter
    }
  `)
}

旧答案

我最近了解到,您甚至可以在其 MarkdownRemark 节点创建之前直接修改 Markdown 的 frontmatter,然后回到这里分享。

gatsby-transformer-remark 使用graymatter 解析frontmatter & 允许用户传入自定义解析器。在内部,graymatter 使用js-yaml

const yaml = require('js-yaml');

const customParser = (str) => {
  const result = yaml.safeLoad(str);

  // remove image (non recursively, as an example)
  const { image, ...withoutImage } = result;

  return withoutImage;
}

并将其传递给gatsby-transformer-remark

{
  resolve: `gatsby-transformer-remark`,
  options: {
    engines: {
      yaml: customParser,
    },
}

在语法上,我更喜欢你这样做的方式——当空字段由插件处理时会更清晰。只是想添加另一个选项!

【讨论】:

    【解决方案2】:

    我最终设法解决了这个问题。我没有意识到在推断架构之前直接从 frontmatter 中删除这些空字段实际上很容易。

    我制作了一个小自定义插件,它会递归地遍历 frontmatter 字段,并且任何具有空字符串的字段都会被删除。我也只允许它删除具有特定名称的字段(例如:image),因此它不会在其他地方引起意外的变化。

    src/plugins/remove-empty-fields/gatsby-node.js:

    let fieldsToRemove = [];
    
    const deleteFieldsRecursive = (node) => {
      fieldsToRemove.forEach(fieldToRemove => {
        if (node[fieldToRemove] === '') {
          delete node[fieldToRemove];
        }
      });
    
      if (typeof node === 'object') {
        Object.values(node).forEach(subNode => {
          deleteFieldsRecursive(subNode);
        })
      }
    };
    
    exports.onCreateNode = ({ node }, configOptions) => {
      fieldsToRemove = configOptions.fieldsToRemove;
    
      if (node.internal.type === 'MarkdownRemark') {
        if (!node.frontmatter) {
          return;
        }
    
        deleteFieldsRecursive(node);
    
      }
    };
    

    然后将此添加到gatsby-config.js的插件列表中

    {
      resolve: 'remove-empty-fields',
      options: {
        fieldsToRemove: [
          'image',
          'bgImage',
        ],
      },
    },
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-05
      • 2015-03-17
      • 2014-02-15
      相关资源
      最近更新 更多