将 ImageSharp 作为字段添加到 MarkdownRemark 节点(不是 frontmatter)

2023-12-10

我正在尝试执行以下 graphQL 查询:

 {
      allMarkdownRemark(
        limit: 1000
      ) {
        edges {
          node {
            id
            parent {
              id
            }
            fields{
              slug
              hero {
                childImageSharp {
                  fixed {
                    src
                  }
                }
              }
            }
            frontmatter {
              template
            }
          }
        }
      }
    }

The hero字段当前使用以下代码返回图像的路径:

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

  // Add slug to MarkdownRemark node
  if (node.internal.type === 'MarkdownRemark') {
    const value = createFilePath({ node, getNode, basePath: 'library' })
    const { dir } = getNode(node.parent)
    const getHero = (d) => {
      let hero = `${__dirname}/src/images/no-hero.gif`
      if (fs.existsSync(`${d}/hero.jpg`)) hero = `${d}/hero.jpg`
      if (fs.existsSync(`${d}/hero.png`)) hero = `${d}/hero.png`
      if (fs.existsSync(`${d}/hero.gif`)) hero = `${d}/hero.gif`
      return hero
    }
    createNodeField({
      node,
      name: 'slug',
      value,
    })

    createNodeField({
      node,
      name: 'hero',
      value: getHero(dir),
    })
  }
}

我见过其他人对图像路径做了类似的事情frontmatter但我不想使用 frontmatter,因为很容易让 graphql 查看文件路径而无需指定它。

但是,当我尝试上述操作时,出现以下错误:

字段“英雄”不能有选择,因为类型“字符串”没有 子字段。

有什么方法可以让我得到childImageSharp认识这个领域?


我再次回来(希望)一劳永逸地解决这个问题(请参阅我们的历史here).

这次,我们将附上英雄图片ImageSharp to the MarkdownRemark节点。你的方法是correct,有 1 个警告:盖茨比似乎只识别相对路径,即以点开头的路径。

您可以在代码中轻松解决此问题:

    const getHero = (d) => {
      let hero = `${__dirname}/src/images/no-hero.gif`

  -   if (fs.existsSync(`${d}/hero.jpg`)) hero = `${d}/hero.jpg`
  -   if (fs.existsSync(`${d}/hero.png`)) hero = `${d}/hero.png`
  -   if (fs.existsSync(`${d}/hero.gif`)) hero = `${d}/hero.gif`

  +   if (fs.existsSync(`${d}/hero.jpg`)) hero = `./hero.jpg`
  +   if (fs.existsSync(`${d}/hero.png`)) hero = `./hero.png`
  +   if (fs.existsSync(`${d}/hero.gif`)) hero = `./hero.gif`

      return hero
    }
    createNodeField({
      node,
      name: 'hero',
      value: getHero(dir),
    })

这应该可行,尽管我想提供替代的英雄搜索功能。我们可以得到文件列表dir with fs.readdir,然后找到一个名为“hero”的文件:

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

  if (node.internal.type === 'MarkdownRemark') {
    const { dir } = path.parse(node.fileAbsolutePath)

    const heroImage = await new Promise((res, rej) => {

      // get a list of files in `dir`
      fs.readdir(dir, (err, files) => {
        if (err) rej(err)

        // if there's a file named `hero`, return it
        res(files.find(file => file.includes('hero')))
      })
    })

    // path.relative will return a (surprise!) a relative path from arg 1 to arg 2.
    // you can use this to set up your default hero
    const heroPath = heroImage 
      ? `./${heroImage}` 
      : path.relative(dir, 'src/images/default-hero.jpg')

    // create a node with relative path
    createNodeField({
      node,
      name: 'hero',
      value: `./${heroImage}`,
    })
  }
}

这样我们就不在乎英雄图像的扩展名是什么,只要它存在即可。我用String.prototype.includes,但为了安全起见,您可能想使用正则表达式传递允许的扩展名列表,例如/hero.(png|jpg|gif|svg)/。 (我认为您的解决方案更具可读性,但我更喜欢每个节点仅访问文件系统一次。)

您还可以使用path.relative查找默认英雄图像的相对路径。

现在,这个 graphql 查询可以工作:

enter image description here


一个(小)问题

然而,这种方法有一个小问题:它破坏了 graphql 过滤器类型!当我尝试查询和过滤时hero,我收到此错误:

enter image description here

也许盖茨比忘记了重新推断类型hero,所以不是File,它仍然是一个String。如果您需要过滤器工作,这很烦人。

这里有一个解决方法:我们不用要求 Gatsby 链接文件,而是自己做。

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

  // Add slug to MarkdownRemark node
  if (node.internal.type === 'MarkdownRemark') {
    const { dir } = path.parse(node.fileAbsolutePath)
    const heroImage = await new Promise((res, rej) => {
      fs.readdir(dir, (err, files) => {
        if (err) rej(err)
        res(files.find(file => file.includes('hero')))
      })
    })

    // substitute with a default image if there's no hero image
    const heroPath = heroImage ? path.join(dir, heroImage) : path.resolve(__dirname, 'src/images/default-hero.jpg')

    // get all file nodes
    const fileNodes = getNodesByType('File')

    // find the hero image's node
    const heroNode = fileNodes.find(fileNode => fileNode.absolutePath === heroPath)
    createNodeField({
      node,
      name: 'hero___NODE',
      value: heroNode.id,
    })
  }
}

And now we can filter the hero field again: enter image description here

如果您不需要按英雄图像过滤内容,那么让 gatsby 处理节点类型会更好。

如果您在尝试此操作时遇到问题,请告诉我。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 ImageSharp 作为字段添加到 MarkdownRemark 节点(不是 frontmatter) 的相关文章

随机推荐

  • Z 索引不起作用

    看看我正在处理的这个页面 http s361608839 websitehome co uk textcube 导航栏位于滑块后面 我希望它位于滑块上方 我尝试在 navbar 和 navbar inner 上设置高 z index 但什么
  • 如何制作适用于另一个平台的 Python virtualenv?

    我正在运行带有 x86 64 处理器的 Ubuntu 的计算机上编写一个程序 该程序需要在运行带有 x86 处理器的 OS X 的计算机上运行 我可能无法进行任何类型的库安装 因此 venv 几乎是我所知道的唯一选择 我怎样才能针对该平台制
  • 防止 IE9 中的 onbeforeunload 对话框

    我在 IE9 中遇到 onbeforeunload 问题 当运行下面的代码时 它会反复弹出一个对话框 询问您是否要保留或离开页面 我修改了我的代码以防止基于默认功能这个线程无济于事 对此的任何帮助将不胜感激 代码示例 window onbe
  • 如何将行数或 getText 分配给 Protractor 中的变量

    这是我的代码 describe SuperCalculator Page function beforeEach function browser get http juliemr github io protractor demo it
  • Swift:在 init 中调用 self 方法

    我想实现这样的事情 class A var a b c d Int init reset func reset a 1 b 2 c 3 d 4 func blablabla 无法编译 错误信息 初始化之前使用的变量 self a 我必须从以
  • PHP将一维数组转换为多维数组

    我有一个数组 tmpArr array A B C 我想处理这个数组并希望新数组为 tmpArr A B C C 即最后一个元素成为最终数组的值 有人能提出解决方案吗 请帮忙 提前致谢 迭代键数组并使用参考对于链的末端 arr array
  • 使用 rfc2254 中指定的 objectGUID 编码的活动目录过滤器不起作用

    我正在使用 java ldap 访问活动目录 更具体地说是 spring ldap 当过滤器按照 rfc2254 中指定的方式进行编码时 按 objectGUID 进行组搜索不会产生任何结果 这是十六进制表示形式的 guid 49 00 f
  • 如何停止或销毁正在运行的线程

    我有一个线程类 其中包含onCreate的一项活动 class MyThread extends Thread void run My code which takes time To run the thread MyThread mTh
  • 如何绘制自定义滑块控件?

    我创建了一个滑块条用户控件 但在运行时 当我向左或向右移动滑块时 为什么它没有到达末尾或吞下 在用户控件设计器中 我添加了一个 pictureBox 控件 然后在我做的代码中 using System using System Collec
  • 如何在 twitter-bootstrap 模式窗口中插入 django 表单?

    有人问过具体情况同样的问题四月份了 没有任何答复 但由于他提供的信息太少 这个问题被放弃了 我也有同样的问题 在一个main page html我有这一行 a href title Edit edit a 单击此处后 编辑模板将出现在 Tw
  • Unity - 通过 XML 的工厂

    我使用 Unity 框架作为 IoC 容器 我的配置看起来像这样
  • 如何在 Javascript 中重新加载页面而不出现 POSTDATA 警告?

    我想使用以下方法重新加载页面 window location reload true 但我收到 POSTDATA 警告 因为刷新功能想要重新发送以前的 POST 表单数据 如何刷新页面而不出现此警告 更新 我无法控制该项目 我无法解决 PO
  • 相对于(也是绝对定位的)父 DIV 的绝对定位 DIV 的位置?

    这是我在修复布局时经常遇到的一个问题 我有一个绝对定位的 DIV 我在里面放置了一个子 DIV 它也需要绝对定位 但我真的希望这个子 DIV 相对于父级的行为 这可能吗 或者我需要创建一个wrap DIV div class contain
  • Protractor如何测试select2

    我有一个 select2 下拉菜单 您需要先输入 2 个字符 然后选择您的项目 我无法用量角器对此进行测试 var select2 element by css div s2id person select2 click select2 s
  • PHP中检查字符串的第一个字符是字母还是数字? [复制]

    这个问题在这里已经有答案了 有没有办法检查字符串的第一个字符是字母还是数字 我不太确定该使用什么功能 有没有办法检查不使用正则表达式 因为我们在课堂上还没有学到这一点 我鼓励您阅读更多有关PHP 中的字符串 例如 您可以像数组一样取消引用它
  • JDBC 中的 Java 类型到 Postgres ltree

    有谁知道什么 Java 类型映射到 Postgres ltree 类型 我创建一个像这样的表 CREATE TABLE foo text name path ltree 一些插入 INSERT INTO foo name path VALU
  • 在 HTML 中使用内联事件处理程序是一种不好的做法吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 使用内联 JavaScri
  • MySQL全文搜索总是有0个结果?

    我读到使用全文搜索比使用 LIKE 更快 我已经更新了我的脚本 但它似乎总是有 0 结果 SELECT MATCH pages AGAINST doodle AS score FROM books WHERE MATCH pages AGA
  • 通过 exec() 从 php 调用 php 没有结果

    我有一个 PHP 脚本 可以根据用户输入创建其他 PHP 文件 基本上 有一些文件包含特定于语言的常量 define 可由用户翻译 为了避免运行时错误 我想测试新编写的文件是否存在解析错误 由于 不寻常 的字符序列 我在这里读过几篇关于SO
  • 将 ImageSharp 作为字段添加到 MarkdownRemark 节点(不是 frontmatter)

    我正在尝试执行以下 graphQL 查询 allMarkdownRemark limit 1000 edges node id parent id fields slug hero childImageSharp fixed src