使用 Gatsby 从富文本组件中将 Markdown 转换为 HTML

IT技术 reactjs markdown gatsby contentful
2021-04-28 15:04:02

我正在使用 Contentful 的 Rich-Text Field 类型来构建页面,我拥有的 Embedded_Blocks 之一是用于我用来构建表格的 Markdown 字段类型:

降价字段类型:

| Title | Title | 
| ---------- | ---------- | 
| Cell | Cell | 

我可以检索富文本数据并像这样构建我的 Embedded_Blocks:

[BLOCKS.EMBEDDED_ENTRY]: (node) => {
   const fields = node.data.target.fields;
   switch (node.data.target.sys.contentType.sys.id) {
      case 'video':
          const url = (fields.url['en-US']);
          return <Video url={url}/>

      // This is how I'm currently trying to convert Markdown to HTML
      ///////////////////////////////////////////////////////////////
      case 'markdown':
          const markdown = (fields.markdown['en-US']);
          console.log('markdown', markdown);
          return <div dangerouslySetInnerHTML={{ __html: markdown }} />
      default:
          return <div>Fallback</div>
   }
},

我遇到的问题是它只返回一个字符串,我假设是因为markdown在将它传递给dangerouslySetInnerHTML={{ __html: markdown }}.

如何将 Markdown 转换为 HTML 以便我可以使用它来呈现它dangerouslySetInnerHTML={{ __html: markdown }}

3个回答

在 Gatsby 内部执行此操作的最合适方法是在 GatsbyonCreateNode生命周期钩子内部创建子节点这个钩子只在nodejs进程中调用,在Contentful条目下载时运行一次markdown解析。

这应该让你开始 - 它基于 Gatsby's 内部的代码 gatsby-transformer-remark

请注意,这是伪代码 - 您当然必须对其进行测试。

// gatsby-node.js

var remark = require('remark')
var recommended = require('remark-preset-lint-recommended')
var html = require('remark-html')

const processor = remark()
  .use(recommended)
  .use(html)

export async function onCreateNode({ actions, node, loadNodeContent}) {
  if (!/RichText/.test(node.internal.type)) {
    return
  }

  const markdown = // somehow load the raw markdown from the node - I haven't studied RichText nodes yet

  const html = processor.process(markdown)

  const markdownNode = {
    id: createNodeId(`${node.id} >>> MarkdownRemark`),
    children: [],
    parent: node.id,
    internal: {
      content: data.content,
      type: `MarkdownRemark`,
    },
  }

  actions.createNode(markdownNode)
  actions.createParentChildLink({ parent: node, child: markdownNode })
}

作为参考,这里是 Contentful 在 Gatsby 中创建富文本节点的地方:

我使用包 react-markdown 实现了解决方案

npm i react-markdown 
//using version "^5.0.2",

从您的问题中,我可以看到您可以将降价内容作为字符串获取。使用上面的包解析 markdown 内容,如下所示:

import ReactMarkdownWithHtml from "react-markdown/with-html";

代替:

return <div dangerouslySetInnerHTML={{ __html: markdown }} />

和:

return <ReactMarkdownWithHtml children={markdown} allowDangerousHtml />

这是他们的 github 页面 react-markdown

你可以使用这个包或任何其他解析 Gatsby 内部降价的 React 包来解析你的降价字符串。

使用“微标记”对我有用......

  1. 我刚刚在 package.json 中添加了依赖项

  2. 在 gatsby.config.js 我添加了包:

    const micromark = require('micromark');

  3. 我用它来转换节点:

    {解决:'@contentful/gatsby-transformer-contentful-richtext',选项:{renderOptions:{renderNode:{

             [BLOCKS.EMBEDDED_ENTRY]:
               (node) => {
                 const LANG = 'en-US';
                 const ENTRY_TYPES = {
                   BUTTON: 'elementbutton',
                   TIP: 'elementtip',
                   QUOTE: 'elementquote',
                   IMAGE_COLUMN: 'elementimagecolumn',
                 };
                 const type = node.data.target.sys.contentType.sys.id;
                 const { fields } = node.data.target;
    
                 switch (type) {
                   case ENTRY_TYPES.QUOTE: {
                     const text = fields.text[LANG];
                     return `
                       <div class="${ENTRY_TYPES.QUOTE}">
                         ${micromark(text)}
                       </div>
                     `;
                   }
                   default:
                     return '';
                 }
               },
           },
         },
       },
     },