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

问题描述

在Gatsby中将MD转换为HTML的标准过程是在本地系统上获取完整文件

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

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

recommended solution要使用解析器进行转换...但是我不能完全理解盖茨比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-config是:

    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`,queryName: 'Premium',

所以现在'allAirtable'变成'allAirtablePremium'。

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

  createResolvers({
    allAirtablePremium: {
      FAQ_html: {
        resolve(source: any,}
  })

但这会引发警告:

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

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

  createResolvers({
    AirtablePremium: {
      FAQ_html: {
        resolve(source: any,}
  })

我又回到了最初的错误,它至少告诉我我尝试返回的内容有问题(因为错误清楚地表明“错误的OutputType”)。

那应该返回什么?

在此先感谢您的帮助!

更新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,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>{field}</Markdown>

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