graphql - 如何在 Gatsby 中使用 createResovers 将 Markdown 字段(不是文件)转换为 HTML

标签 graphql gatsby airtable

Gatsby 中将 MD 转换为 HTML 的标准流程适用于本地系统上的完整文件。

我需要转换特定字段,而不是文件。最相关的问题是 this one ,但正如您所看到的,这是使用 Contentful,它现在提供了一个插件来解决它。

我正在使用的 API (Airtable) 返回一个包含 Markdown 的字段。

recommended solution是使用解析器进行转换...但我无法完全理解 Gatsby docs on the topic .

我在构建时看到的错误是这样的:

UNHANDLED REJECTION Airtable.FAQ provided incorrect OutputType:
 'Object({ resolve: [function resolve], extensions: Object({ createdFrom: "createResolvers" }) })'

我想我已经很接近了,但我不知道我是否要创建一个新类型,或者解析器实际上要返回什么......一个新字段?

相关字段是 FAQ,您可以在 GraphQL 浏览器中的查询示例中看到该字段:

query MyQuery {
  allAirtableManufacturer(filter: {data: {Premium: {eq: true}}}) {
    edges {
      node {
        data {
          Premium
          Manufacturer
          Premium_Manufacturers {
            recordId
            data {
              FAQ
              Downloads_File_Name
              Is_Supplier
            }
            internal {
              type
            }
          }
        }
        recordId
        queryName
      }
    }
  }
}

我的理解是解析器可以/应该添加一个新字段,将 markdown 内容转换为 html。

这是我的解析器代码,您可以在其中看到我正在尝试向 Airtable 节点添加一个名为“FAQ_html”的字段:

  createResolvers({
    Airtable: {
      FAQ_html: {
        resolve(source: any, args: any, context: any, info: any) {
          return remark().use(html).processSync(source.data.FAQ).contents
        },
      },
    }
  })

我的airtable gatsby 配置是:

    resolve: `gatsby-source-airtable`,
      options: {
        apiKey: process.env.AIRTABLE_API_KEY,
        concurrency: 5,
        tables: [
          {
            baseId: `appP5vBdAitw6yyDH`,
            tableName: `Manufacturers`,
            queryName: `Manufacturer`,
            tableView: `AppView_Details_DONOTCHANGE`,
            tableLinks: [`Premium_Manufacturers`],
            separateNodeType: true,
            defaultValues: {
              Company_Description: '',
            },
          },
          {
            baseId: `appP5vBdAitw6yyDH`,
            tableName: 'Premium_Manufacturers',
            tableLinks: [`Manufacturers`],
          },

        ],

表“Premium_Manufacturers”显然作为子表链接到“Manufacturers”。

但是,当我在 GraphQL 中探索时,我还看到它们显示为名为“Airtable”的顶级节点,这是我没想到的。您可以在这里看到:

allAirtable {
    edges {
      node {
        data {
          FAQ
          Downloads_File_Name
          Last_update
          Is_Supplier
          Section_Name
          Section_No
          Name
          Cell_Number
          Email
          Rep_Name
          Technical_Rep_Name
          Consolidated_Rep
        }
      }
    }
  }

这就是为什么我的解析器使用“Airtable”作为节点名称,但显然它不起作用。

我还尝试更改配置以提供单独的节点:

          {
            baseId: `appP5vBdAitw6yyDH`,
            tableName: 'Premium_Manufacturers',
            queryName: 'Premium',
            separateNodeType: true,
            tableLinks: [`Manufacturers`],
          },

现在“allAirtable”变为“allAirtablePremium”。

我尝试更改解析器以使用它:

  createResolvers({
    allAirtablePremium: {
      FAQ_html: {
        resolve(source: any, args: any, context: any, info: any) {
          return remark().use(html).processSync(source.data.FAQ).contents
        },
      },
    }
  })

但这会引发警告:

warn `createResolvers` passed resolvers for type `allAirtablePremium` that doesn't exist in the schema.

很明显它不喜欢“全部”,所以我将其更改为删除“全部”,如下所示:

  createResolvers({
    AirtablePremium: {
      FAQ_html: {
        resolve(source: any, args: any, context: any, info: any) {
          return remark().use(html).processSync(source.data.FAQ).contents
        },
      },
    }
  })

我又回到了原来的错误,这至少告诉我我试图返回的内容有问题(因为错误清楚地表明“输出类型错误”)。

那么应该返回什么?

预先感谢您的帮助!

更新1

代码现在可以编译,但我没有看到我的自定义字段。

这是架构自定义(只需将 FAQ_HTML 创建为空字符串即可开始):

import { GatsbyNode, CreateSchemaCustomizationArgs } from 'gatsby'

export const createSchemaCustomization: GatsbyNode['createSchemaCustomization'] = async ({
  actions,
}: CreateSchemaCustomizationArgs) => {

  const { createFieldExtension, createTypes } = actions
  createFieldExtension({
    name: "FAQ_HTML",
    extend() {
      return ''
    },
  })

  const typeDefs = `
    type airtablePremium implements Node {
      FAQ_HTML: String @FAQ_HTML
    }
`

  createTypes(typeDefs)
}

解析器现在是这样的:

  createResolvers({
    airtablePremium: {
      FAQ_HTML: {
        resolve(source: any, args: any, context: any, info: any) {
          console.log("SOURCE IS", source)
          const faqHtml = remark().use(html).processSync(source.FAQ).contents
          console.log("faqHtml IS", faqHtml)
          return faqHtml;
        },
      },
    },
  })

它可以编译,但该字段不会显示在 GraphQL 资源管理器中。也没有控制台输出。

最佳答案

与@rmcsharry 进行了愉快的交谈后,我们确认您需要先创建类型。

createTypes(`
  type AirtablePremium implements Node @infer {
    FAQ_HTML: String
  }
`)

最大的问题是类型名称。在代码中,应该是 AirtablePremiumairtablePremium。您可以通过单击左列中的字段名称,或按住 cmd 并单击查询中的字段来找到 GraphiQL 中的类型名称。

您也可以在 createResolvers 中使用类型名:

  createResolvers({
    AirtablePremium: {
      FAQ_HTML: {
        resolve(source: any, args: any, context: any, info: any) {
          ...
        },
      },
    },
  })

来自@rmcsharry的更新

在 @Derek Nguyen 非常有帮助的帮助后,我找到了一个替代且更简单的解决方案。

如果您想避免创建类型的麻烦,您可以使用插件 markdown-to-jsx 来采用更简单的解决方案。 .

然后你只需包装传入的 markdown 字段即可:

<Markdown>{field}</Markdown>

它会动态创建一个 React JSX 组件。 :)

关于graphql - 如何在 Gatsby 中使用 createResovers 将 Markdown 字段(不是文件)转换为 HTML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64475227/

相关文章:

graphql,当有 "add"和 "update"突变时如何设计输入类型?

javascript - 如何在 Vue 中从 graphql 数据集创建动态过滤?

javascript - 如何在 gatsby 博客网站中验证 graphql

reactjs - 无法查询类型 "allMdx"上的字段 "Query"

swift - graphql apollo 无法运行脚本

typescript - 如何使用 jest 测试 Apollo Server 订阅?

python - 使用 python 创建字段时无法验证 Airtable API

javascript - 使用 Airtable.js 时如何从 done() 回调返回数据?

javascript - 如何在 Gatsby 网站中添加 bootstrap js

javascript - 如何使用 Node js 在airtable api 中进行异步等待工作,以在发送解析之前获取airtable 中的所有记录?