【问题标题】:Convert Markdown to HTML from within a Rich-Text Component with Gatsby使用 Gatsby 从富文本组件中将 Markdown 转换为 HTML
【发布时间】:2019-09-23 16:02:30
【问题描述】:

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

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 }} 之前,我没有将其转换为 HTML。

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

【问题讨论】:

  • 返回字符串到底是什么?为什么这是一个问题? markdown 应该是 dangerouslySetInnerHTML={{ __html: markdown }} 中的字符串
  • 我的理解是 dangerouslySetInnerHTML={{ __html: markdown }} 要求 Markdown 文本已经被转换为包含 HTML 的字符串。这不是我所拥有的。 const markdown = (fields.markdown['en-US']); 只是给了我一串未转换的降价。所以dangerouslySetInnerHTML 只是显示标记文本的刺痛,因为没有 HTML。
  • 那么您需要先将其转换为 html 使用例如markdown-it 或gatsbyjs.org/packages/gatsby-transformer-remark
  • @mb21 不确定 D'uh 是否值得。我的问题清楚地表明,转换为 HTML 是我遇到的问题,很明显我知道危险的 SetInnerHTML 的用途。我是在寻求帮助,而不是一种聪明的态度。在暗示愚蠢之前,请仔细阅读问题。

标签: reactjs markdown gatsby contentful


【解决方案1】:

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

这应该可以帮助您入门 - 它基于 Gatsby 的 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 })
}

供参考,here is where Contentful creates the Rich Text nodes inside Gatsby:

【讨论】:

    【解决方案2】:

    我使用包 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 中解析 markdown 的 React 包来解析你的 markdown 字符串。

    【讨论】:

      【解决方案3】:

      使用“micromark”对我有用...

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

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

        const micromark = require('micromark');

      3. 我用它来转换节点:

        { 解决:'@contentful/gatsby-transformer-contentful-richtext', 选项: { 渲染选项:{ 渲染节点:{

                 [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 '';
                     }
                   },
               },
             },
           },
         },
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-02-05
        • 1970-01-01
        • 1970-01-01
        • 2021-06-19
        • 2012-08-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多