如何使用 Contentful 的 rich-text-react-renderer 格式化带有 <pre> 标签的代码片段?

use*_*309 1 contentful gatsby

我正在使用 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 的格式正确的代码片段?

Sal*_*lor 6

内容丰富的 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)