如何使用 createResovers 将 Markdown FIELD(不是文件)转换为 Gatsby 中的 HTML
How to use createResovers to convert a Markdown FIELD (not a file) to HTML in Gatsby
在 Gatsby 中将 MD 转换为 HTML 的标准过程是针对本地系统上的完整文件。
我需要转换特定字段,而不是文件。最相关的问题是 this one,但正如您所见,它正在使用 Contentful,它现在提供了一个插件来解决它。
我正在使用的 API (Airtable) returning 一个包含 Markdown 的字段。
recommended solution is to convert using a resolver...but I cannot fully understand the Gatsby docs on the topic.
我在构建时看到的错误是这样的:
UNHANDLED REJECTION Airtable.FAQ provided incorrect OutputType:
'Object({ resolve: [function resolve], extensions: Object({ createdFrom: "createResolvers" }) })'
我想我已经很接近了,但我不知道我是要创建一个新类型还是实际上解析器对 return...一个新字段意味着什么?
有问题的字段是 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
}
}
}
}
我的理解是解析器can/should添加了一个新字段,markdown内容转换为html。
这是我的解析器代码,您可以在其中看到我正在尝试将名为“FAQ_html”的字段添加到 Airtable 节点:
createResolvers({
Airtable: {
FAQ_html: {
resolve(source: any, args: any, context: any, info: any) {
return remark().use(html).processSync(source.data.FAQ).contents
},
},
}
})
我的gatsby-config空气table是:
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`],
},
],
table 'Premium_Manufacturers' 显然作为 child 链接到 'Manufacturers'。
然而,当我在 GraphQL 中探索时,我也看到它们显示为一个名为 'Airtable' 的 top-level 节点,这是我没有想到的。你可以在这里看到:
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.
很明显它不喜欢 'all',所以我将其更改为删除 'all',如下所示:
createResolvers({
AirtablePremium: {
FAQ_html: {
resolve(source: any, args: any, context: any, info: any) {
return remark().use(html).processSync(source.data.FAQ).contents
},
},
}
})
我又回到了最初的错误,它至少告诉我我正在尝试的东西有问题 return(因为错误清楚地表明 'wrong OutputType')。
那么 return 应该是什么?
在此先感谢您的帮助!
更新 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
}
`)
最大的问题是类型名称。在代码中,它应该是AirtablePremium
vs airtablePremium
。您可以通过单击左栏中的字段名称,或按住 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 组件。 :)
在 Gatsby 中将 MD 转换为 HTML 的标准过程是针对本地系统上的完整文件。
我需要转换特定字段,而不是文件。最相关的问题是 this one,但正如您所见,它正在使用 Contentful,它现在提供了一个插件来解决它。
我正在使用的 API (Airtable) returning 一个包含 Markdown 的字段。
recommended solution is to convert using a resolver...but I cannot fully understand the Gatsby docs on the topic.
我在构建时看到的错误是这样的:
UNHANDLED REJECTION Airtable.FAQ provided incorrect OutputType:
'Object({ resolve: [function resolve], extensions: Object({ createdFrom: "createResolvers" }) })'
我想我已经很接近了,但我不知道我是要创建一个新类型还是实际上解析器对 return...一个新字段意味着什么?
有问题的字段是 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
}
}
}
}
我的理解是解析器can/should添加了一个新字段,markdown内容转换为html。
这是我的解析器代码,您可以在其中看到我正在尝试将名为“FAQ_html”的字段添加到 Airtable 节点:
createResolvers({
Airtable: {
FAQ_html: {
resolve(source: any, args: any, context: any, info: any) {
return remark().use(html).processSync(source.data.FAQ).contents
},
},
}
})
我的gatsby-config空气table是:
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`],
},
],
table 'Premium_Manufacturers' 显然作为 child 链接到 'Manufacturers'。
然而,当我在 GraphQL 中探索时,我也看到它们显示为一个名为 'Airtable' 的 top-level 节点,这是我没有想到的。你可以在这里看到:
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.
很明显它不喜欢 'all',所以我将其更改为删除 'all',如下所示:
createResolvers({
AirtablePremium: {
FAQ_html: {
resolve(source: any, args: any, context: any, info: any) {
return remark().use(html).processSync(source.data.FAQ).contents
},
},
}
})
我又回到了最初的错误,它至少告诉我我正在尝试的东西有问题 return(因为错误清楚地表明 'wrong OutputType')。
那么 return 应该是什么?
在此先感谢您的帮助!
更新 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
}
`)
最大的问题是类型名称。在代码中,它应该是AirtablePremium
vs airtablePremium
。您可以通过单击左栏中的字段名称,或按住 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 组件。 :)