我正在使用 Contenful 作为我的 Gatsby 网站的 CMS。在其富文本反应渲染器的配置中,我尝试将富文本字段中的所有代码包装在标签中,<pre>以便维护所有格式并添加我自己的样式。
这是我尝试过的:
const Blog = (props) => {
const Code = ({children}) => <pre><code style={{backgroundColor: "red"}}>{children}</code></pre>
const options = {
renderMark: {
[MARKS.CODE]: code => <Code>{code}</Code>},
}
}
Run Code Online (Sandbox Code Playgroud)
问题是,当我选择“普通文本”时,Contentful 会将每一行代码片段包装在段落标签内,这不是有效的 HTML(<pre>标签不能是<p>标签的直接后代),并且会弄乱我的所有格式。
有谁知道如何覆盖该行为或解决方法,以呈现来自 Contentful in Gatsby 的格式正确的代码片段?
内容丰富的 DevRel 在这里
已经提交了将<code>标签包装在<pre>标签中的票证,因此该功能可能很快就会可用,同时,我发现解决此问题的方法是为代码块创建单独的内容类型,并将它们作为条目嵌入到 Rich 中。文本字段编辑器。
在代码块内容类型中,我添加了字段description(以帮助我识别它)、language(用于使用 Prism 等进行样式设置)和code(使用类型 markdown)。
这是 Contentful UI 中代码块内容类型的屏幕截图
然后,使用@contentful/rich-text-react-renderer该插件附带的gatsby-source-contentful/rich-text,我创建了一个定制的选项函数,该函数解析链接的条目以传递到该renderRichText函数中,将代码块呈现为带有我需要的 HTML 的嵌入条目。
以下是 GraphQL 查询,它将代码块作为链接引用获取:
query pageQuery($id: String!) {
contentfulBlogPost(id: { eq: $id }) {
title
slug
# This is the rich text field
bodyRichText {
raw
references {
... on ContentfulCodeBlock {
contentful_id
__typename
description
language
code
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
以下是使用该函数将代码块与 HTML 内联呈现的代码renderRichText:
import { BLOCKS, INLINES, MARKS } from "@contentful/rich-text-types"
import { renderRichText } from "gatsby-source-contentful/rich-text"
const options = {
renderNode: {
[BLOCKS.EMBEDDED_ENTRY]: (node) => {
const { __typename } = node.data.target;
switch (__typename) {
case "ContentfulCodeBlock":
const { language, code } = node.data.target;
return (
// add your custom <pre> tags here
<pre className={language}}>
<code>{code}</code>
</pre>
);
default:
return null;
}
},
},
}
// render it
renderRichText(post.richText, options)
Run Code Online (Sandbox Code Playgroud)