Gatsby: 在Markdown源代码中使用React组件

创建于 2016-06-05  ·  112评论  ·  资料来源: gatsbyjs/gatsby

有没有一种简单的方法可以在我的Markdown源代码中使用React组件。 像reactdown这样的

question or discussion

最有用的评论

因此,我一直在尝试一种几乎永远混合使用React和Markdown的干净方法。 或者至少自从我开始从事盖茨比的工作以来。

最后,我认为我有一个可行的想法。

我们将使用与JSX一样的规则来区分普通HTML元素和React组件,即React大写。

因此,您可以将React组件直接包含在Markdown中,例如

# Hi folks

I'm writing some markdown about speaker <Person id="Paul Ryan">Paul Ryan</Person> who's the speaker of the house and other stuff.

<InteractiveComponent invertedColors={true} allTheProps={true} />

然后将其解析为AST,例如:

[
  [{ raw: true, value: "<h1>Hi Folks</h1>" }],
  [
    { raw: true, value: "<p>I'm writing some markdown about speaker " },
    {
      raw: false,
      value: {
        name: "Person",
        props: { id: "Paul Ryan", children: "Paul Ryan" }
      }
    },
    { raw: true, value: " who's the speaker of the house and other stuff.</p>" }
  ],
  [
    {
      raw: false,
      value: {
        name: "InteractiveComponent",
        props: { invertedColors: true, allTheProps: true }
      }
    }
  ]
];

然后在您的组件中,而不是直接呈现(危险样式)HTML,而是将其传递给具有每个React组件映射的辅助函数,例如:

import React from "react";
import renderHtmlReact from "gatsby-render-html-react";
import Person from "../components/Person";
import InteractiveComponent from "../components/InteractiveComponent";

export default ({ data }) => (
  <div>
    {renderHtmlReact({
      ast: data.markdownRemark.ast,
      componentMap: { Person, InteractiveComponent }
    })}
  </div>
);

// Your query goes down here

我们需要做一些原型设计,以确保它可以与Remark一起使用,但是我很确定React“ Html”将不被改动地通过。 因此,我们只需要一个解析器来拆分HTML,并将React JSX部分转换为数据以及前端库以呈现结果的“ AST”。

有什么想法吗?

所有112条评论

这是一个好主意。 如果尚不可用,我将继续努力。

我是reactdown的开发者。 看到reactdown与Gatsby一起工作真是太棒了。 如果您有任何疑问或需要有关集成的帮助,请与我联系。

👍这是一个普遍的要求,因此拥有可以广泛使用的功能非常好!

我建立了一个快速而肮脏的示例存储库,以了解如何使用gatsby进行reactdown。 值得一提的是,盖茨比(Gatsby)只是Webpack顶部的一个非常用户友好的包装器,因此,所有功能仍然可以用来做任何事情。

https://github.com/benstepp/gatsby-reactdown

谢谢,我会尝试的,并让您知道它的运行情况。

太酷了! 好的本。 设置比我想象的要简单得多
哈哈。 做得好,安德烈。

在2016年6月7日星期二晚上10:31 Jo Meenen [email protected]写道:

谢谢,我会尝试的,并让您知道它的运行情况。

-
您收到此邮件是因为您发表了评论。

直接回复此电子邮件,在GitHub上查看
https://github.com/gatsbyjs/gatsby/issues/312#issuecomment -224492088,
或使线程静音
https://github.com/notifications/unsubscribe/AAEVh-2doZe_FXFMBxYTJ5FAVqo4XqxNks5qJlO6gaJpZM4Iubim

@benstepp不错! 当通过包装器使用Markdown文件时,这看起来很简单,但是当导入Markdown文件以在React组件中使用时,这也行得通吗?

编辑:似乎它应该开箱即用,但是以某种方式将md文件转换成的React组件不会输出任何内容…

我一直在考虑新的GraphQL层(#420)打开的另一种方法。 我在mdash仓库https://github.com/wooorm/mdast/issues/13中打开了一个问这个问题的问题

太棒了! 我觉得我与Reactdown是如此接近……markdown文件已通过webpack正确地转换为React组件(至少看起来像它),但是当我在代码中使用它们时,它只是给了我空的组件。

@SachaG在某个地方可以找回购协议吗?

哇真奇怪我试图复制该问题,现在可以了! 甚至不知道发生了什么变化...我猜不能抱怨:)

React的众神降落在一辆金色战车中,瞧! 该代码有效

@SachaG我记得

你好! 最近有没有更新? 在markdown中使用react组件的推荐方法是什么? 有没有我可以效仿的例子? 谢谢!

还没有:-(我有个很好的计划-基本上将markdown文件编译成一个React组件文件,您可以在其中正确导入所有引用的React组件,但还不需要构建它。如果需要,请开始研究!

@KyleAMathews您是说我应该在我的markdown文件上运行一个转换器脚本,然后将我需要的其他其他反应组件手动添加到转换步骤生成的输出文件中吗? 一旦完成,然后进行最终构建?

理想情况下,这将是Gatsby v1的插件,它将执行以下步骤
自动。

2017年5月2日,星期二,下午12:50 Piyush Singh [email protected]写道:

@KyleAMathews https://github.com/KyleAMathews你是说我应该跑步
我的markdown文件上的转换器脚本,然后添加其他反应
组件我需要转换步骤生成的输出文件吗? 一旦
完成此操作,然后完成最终构建?

-
您收到此邮件是因为有人提到您。

直接回复此电子邮件,在GitHub上查看
https://github.com/gatsbyjs/gatsby/issues/312#issuecomment-298741837
或使线程静音
https://github.com/notifications/unsubscribe-auth/AAEVh4riB8uXgeRUybcR6OxsC1EAKnkKks5r14kPgaJpZM4Iubim

我的意思的简单例子。

假设您在/my-blog/index.md中拥有一个markdown文件,该文件如下所示:

---
title: "hi folks"
---

# This is my broomstick

Yo yo foo

<SweetComponent props="super cool" />

然后可以将主体转换为可通过webpack / babel / etc运行的react组件。 像平常一样。

import React from 'react'
import SweetComponent from 'auto-resolve-this-somehow'

class MarkdownBody extends React.Component {
  render () {
    return (
      <div>
        <h1>This is my broomstick</h1>
        <p>Yo yo foo</p>
        <Sweet Component props="super cool" />
      </div>
    )
  }
}

技巧部分是如何将其与Gatsby的graphql系统集成。 理想情况下,您可以只查询markdown文件的“组件”版本,类似于今天查询html的方式。

无论如何,这只是我所想的简短概述。

@KyleAMathews谢谢,我想我现在明白了。

我的目标是能够编写这样的内容,这些内容利用MathJax,D3.js可视化效果,并且还可以在markdown源代码中合并Three.js动画组件。

如果您在此处看到

从到目前为止的经验来看,我认为用Gatsby框架生成这样的内容可以以更加整洁和结构化的方式实现,是吗?

我是Web开发的新手,但是我会尽力学习Gatsby系统的工作方式,以便为实现这些目标做出贡献...

@KyleAMathews ,我一直在考虑您提出的解决方案。

您是否认为可以使用或改进诸如markdown-it-jsx之类的东西来执行到所需的MD JS组件结构的转换?

为了解决auto-resolve-this-somehow部分,也许第二个解析器可以扫描MD JS组件文件以查找与组件注册表列表中的JSX匹配的JSX(可以是简单的文本文件,也可以在目录中查找文件,其中所有组件都将被存储),然后将相关的导入行添加到文件顶部?

我将开始着手研究,以便任何反馈都很棒!

请注意,还有另一个项目正在执行此操作,也许它将对参考很有用: react-styleguidist降价文件示例

在markdown中启用组件使我想起了Bret Victor的杰作

UPD:还有另一个示例: mdxc

还有一个http://thejameskyle.com/react-markings.html

一个解决方案是使用react-jsx-parser
在howtographql.com上,我们正在生产中使用它: https :

一个缺点:它比仅使用dangerouslySetInnerHTML慢,因为它

  1. 解析HTML
  2. 构造一个虚拟的dom树
  3. 使用React渲染虚拟树

加快这一种方法是不发送与graphql查询原始的HTML,但实际上发送格式的文档Inferno.js使用,如所描述这里

由于我目前没有时间进行优化的最后一步,因此对此感兴趣的任何人都可以采用这种方法。

那意味着

  1. 构造适当的GraphQL类型,这不应该成为问题,因为GraphQL类型可以是递归的并代表一棵树
  2. 完成remark降价解析业务后,生成序列化的jsx格式。
  3. 在React中反序列化此格式。

我一直关注的另一个选择是https://github.com/mapbox/jsxtreme-markdown

我们可以使用类似的模式。 只需将markdown转换为JSX组件即可。 使用自定义定界符添加JavaScript和JSX。 我们可以使用现有的Remark设置就可以了。 而且不会有太多的性能损失,因为它只是正常的React页面。

还有https://github.com/cerebral/marksy ,我最近使用它效果很好。

在盖茨比的背景下是否有建议的方法还是尚待确定?

嗨,有什么建议在我们的gatsby markdown文件中包含海关组件?

看起来markmark非常适合该用例

当它返回一个react elements树时,我想知道如何将其集成到gatsby插件中?

@KyleAMathews @revolunet您如何注册需要用作自定义元素的组件,之后我们可以简单地将它们包含在博客文章中,并将其余的工作留给浏览器去做?

这将消除将markdown解析为反应树并保持应用程序性能的任何需要,但是,我不知道是否会有性能成本,每次我们需要添加一个新的ReactDOM.render自定义组件,但仍然可以为我们提供一种非常酷的方式来向博客文章添加动态功能。

@abdulhannanali注册在markdown中可用的组件是一个好主意,但是自定义元素的东西听起来不是服务器端友好的:)

因此,我一直在尝试一种几乎永远混合使用React和Markdown的干净方法。 或者至少自从我开始从事盖茨比的工作以来。

最后,我认为我有一个可行的想法。

我们将使用与JSX一样的规则来区分普通HTML元素和React组件,即React大写。

因此,您可以将React组件直接包含在Markdown中,例如

# Hi folks

I'm writing some markdown about speaker <Person id="Paul Ryan">Paul Ryan</Person> who's the speaker of the house and other stuff.

<InteractiveComponent invertedColors={true} allTheProps={true} />

然后将其解析为AST,例如:

[
  [{ raw: true, value: "<h1>Hi Folks</h1>" }],
  [
    { raw: true, value: "<p>I'm writing some markdown about speaker " },
    {
      raw: false,
      value: {
        name: "Person",
        props: { id: "Paul Ryan", children: "Paul Ryan" }
      }
    },
    { raw: true, value: " who's the speaker of the house and other stuff.</p>" }
  ],
  [
    {
      raw: false,
      value: {
        name: "InteractiveComponent",
        props: { invertedColors: true, allTheProps: true }
      }
    }
  ]
];

然后在您的组件中,而不是直接呈现(危险样式)HTML,而是将其传递给具有每个React组件映射的辅助函数,例如:

import React from "react";
import renderHtmlReact from "gatsby-render-html-react";
import Person from "../components/Person";
import InteractiveComponent from "../components/InteractiveComponent";

export default ({ data }) => (
  <div>
    {renderHtmlReact({
      ast: data.markdownRemark.ast,
      componentMap: { Person, InteractiveComponent }
    })}
  </div>
);

// Your query goes down here

我们需要做一些原型设计,以确保它可以与Remark一起使用,但是我很确定React“ Html”将不被改动地通过。 因此,我们只需要一个解析器来拆分HTML,并将React JSX部分转换为数据以及前端库以呈现结果的“ AST”。

有什么想法吗?

然后在您的组件中,而不是直接呈现(危险样式)HTML,而是将其传递给具有每个React组件映射的辅助函数,例如:
[…]
有什么想法吗?

这也是我们一直在做的事情(非常简化,实际上并不安全,仅针对特定标签而设计)。 我们的用例是设置样式/布局JSON文档:

<IconGrid src="sensors.json" />

这对于避免重复的内容确实很有帮助,我们正在考虑对可重用的API文档组件使用类似的机制。

该解决方案缺乏的东西(我们也没有解决)是在组件属性中使用markdown。 这样就有可能:

<Api method="post" description="
An API which uses **markdown**.

And having multi line parameters would be helpful as well.
" />

在此空间中尝试了很多东西之后,我深信是的,确实需要在降价级别解决它。 意味着降价的味道确实需要了解jsx / react。 问题实际上是javascript内插jsx支持和markdown阻塞。 Jsxtreme-markdown接近并通过首先处理它们然后使用markdown解析其余部分来解决此问题。 另一种方法是依靠MD解析器的自然能力来处理html,因此直接使用jsx(例如,Marked将处理大写元素),但是您很快就会遇到恼人的局限性,因为它仅停留在字符串道具上而没有嵌套的markdown(例如Markdown里面,props.children)。 另一个问题是客户端上的水合作用很烦人,因为您需要一个运行时(通常是一个相当大的运行时间)才能将字符串转换为反应元素,这对于gatsby专注于快速实现交互和性能而言并不理想。

我确实认为最有前途的方法是基于ast的方法,但是为此,您确实需要Markdown变种的速度,与现有的速度足够不同,这是一个相当大的项目

只需投入我的2美分!

在我知道盖茨比存在之前(2年前),我试图制造一个反应类似于jekyll

选择使用正则表达式在降价内容中找到<CapitalizedComponents/> ,但效果很好,除了有一些边缘情况。 当时,我使用的是mark标记,它们在解析html时有一些奇怪的副作用。

另外,我的简单正则表达式不允许使用组件结束标记,因此也就没有子代...因此这是行不通的:

<Component>
   <Child/>
</Component>

无论如何,我很高兴盖茨比能支持这一点! 我正在将我的jekyll网站转换为gatsby,并且我已经完成了。 我的下一个任务是弄清楚如何将md博客文章中包含的jekyll更改为gatsby版本的组件。

@jquense同意在markdown中不支持JS是一个限制。 但从好的方面来说,这很适合我们现有的结构。 运行时库非常简单,只需递归循环AST创建元素即可。 我们还可以将其设置为自动解析组件的任何子级文本作为markdown,因此用于此组件的组件只需props.children dangerouslySetInnerHTML props.children

这不是100%的解决方案,但适用于许多设置。 我也不是喜欢在markdown内编写JS的想法。 这样您将失去所有工具支持。

@jakedeichert是的,简单的正则表达式仅适用于此。 太酷了,您得到了类似的功能! 这证实了这一概念。 我们想使用了解JSX的JS解析器来提取结构化信息。 这样我们就可以支持嵌套组件。

@KyleAMathews您提出的建议有什么进展?

关于此的一些想法:

  1. 我有一个工作示例,该示例使用remark转换包含任意反应组件tmp-remark-jsx的markdown 。 我使用remark-htmlhast-util-to-html作为基础项目。
    这是用法+输出的示例
    如果您有兴趣,我可能会提供更多有关其工作方式的信息。
  2. MapBox创建了一个remark-react包,该包将markdown转换为使用remark的react元素。 可能需要一些工作才能使程序包适应自定义反应元素。

没有人开始对其进行afaik的研究。

这两种方法的问题在于它们不能与基于Gatsby的GraphQL的数据系统一起使用,因为GraphQL查询只能返回未运行代码的数据。 例如remark-react会在客户端进行markdown => html转换来解决此问题,这比理想情况贵。

因此,要使用GraphQL,您需要一个客户端运行时来创建React组件。 我的建议来自于通过设计实现尽可能最小的运行时间。

我想我现在明白了。 因此,您认为需要两段代码:

  1. markdown->准备使用支持React组件的HAST。 (此代码应在构建时运行吗?)
  2. 启用了HAST的react-> react元素(这应该在客户端运行,运行时间最少/平凡)

我说对了吗? 我想念什么吗?

对!

跑过这个领域的另一个项目-有一些有趣的想法https://github.com/luiscarli/md-to-react

你好

我又要刺了一下。 我有第一部分的工作示例,在这里创建了HAST remark-custom-element-to-hast 。 它仍然需要支持将markdown用作子元素,也许还需要使用它的webpack加载器。

@KyleAMathews您认为该方法符合您的观点吗?

至于第二部分,我们可以使用语法树/快速到超脚本。 这是用法wooorm / remark-vdom的示例

@ fazouane-marouane酷! 是的,从快速的角度看,它似乎非常接近。 做得好!

我们不想在前端使用hasto-to-hyperscript,因为它有很多依赖关系,并且我们希望运行时尽可能轻巧-例如,通过创建React元素的AST递归。 因此,将第二个库中的尽可能多的内容移到您的模块中。

@KyleAMathews那太好了! 我将在接下来的几天中尝试执行剩余的步骤。 希望这将使我们更接近实际解决方案。

@ fazouane-marouane和@KyleAMathews ,您好,我阅读了您的讨论,并在您正在开发的此应用程序上实现了您在此处描述的各个部分的“简单”版本。

有趣的部分是使用@ fazouane-marouane代码的形式(此处是gatsby插件) 在此处渲染HAST的部分。 借助GraphQL,了解如何检索HAST也可能很有趣。

请注意,在撰写本文时,它还远非完美,优化和干净。

编辑:我的renderHAST组件在很大程度上受到了客户端处理渲染降价的现象处理方式的启发: https

@pbellon感谢您的加入! 这将节省每个人很多时间。 该代码似乎在完成其余步骤所需的工作。 我今晚晚些时候尝试。

我需要调试的一件事是处理组件子项的方法。
现在,如果我设置了markdown This is a test <MyComponent>let's see how children are handled</MyComponent>的写操作,则MyComponentchildren属性将设置为[0, null]

但是我不确定它来自解析器还是来自HAST的混合方式。

@pbellon它来自解析器。 这是一个极简主义的解析器,用于对整个Markdown事件做出反应。 它肯定需要一些修复程序才能在所有情况下都可用。 如果遇到更多示例,请随时提交问题。 无论如何,这将有助于建立良好的测试基础。

@ fazouane-marouane我明白了。 我会尝试使用您的代码,看看我是否可以实现此功能(如果可以做到的话,可以进行PR),但这似乎不是一个小小的修改😮
我在这里在您的仓库上创建了一个问题

用我的$ 0.02赚钱。 作为开发GitDocs的一部分,我们需要一种允许用户将JSX嵌入markdown文件中的方法。 这是到目前为止我得到的。

降价解析

降价处理使用统一备注重新宣传。 从注释块HTML标记器派生了一个自定义标记器,并带有一个额外的正则表达式来检测JSX。 该令牌生成器允许重新炒作将JSX块检测为raw进行进一步处理。

我编写了一个自定义的rehype插件,其功能类似于rehype-raw,但支持JSX和一些基本的表达式评估。 该插件查找raw节点,并尝试通过使用acorn-jsx解析该块来确定它们是否为JSX。 如果解析成功,则橡子产生的JSX AST将转换为HAST。

支持的JSX

到目前为止,我可以转换以下JSX位(示例案例来自测试套件)

<Test>
  <Test2></Test2>
</Test>
<Test>some text</Test>
<Test attr={{ prop: 400 }} />

表达方式

支持简单的编译时表达式评估。

<Test attr={1 + 2}/>

创建的HAST节点将属性'attr'设置为3

数组表达式

在属性中允许使用Array.prototype.map()

<Test attr={ [1,2,3].map(x => 2 * x) } />

您甚至可以映射数组并创建JSX子级

<Test>{ [1,2,3].map(x => (<Test2>{x}</Test2>)) }</Test>

将被翻译成HAST,相当于

<Test>
  <Test2>1</Test2>
  <Test2>2</Test2>
  <Test2>3</Test2>
</Test>

局限性

表达式支持非常有限,尚未经过安全审查。 该代码不使用eval应该无法访问window类的东西,但我不能做任何保证。

我在这一领域进行了实验,您可以像往常一样充分使用gatsby备注插件。 您将graphql html传递到Webpack加载器,该加载器生成react.js代码。 不幸的是,它有几个问题,并且破坏了单个生产版本。

          createPage({
            path: edge.node.fields.slug,
            component: getCdResolve(blogPost, edge.node.fileAbsolutePath, {
              html: edge.node.html,
              site: result.data.site,
            }),
            context: {
              slug: edge.node.fields.slug,
            },
          })

其中cdResolve返回类似!!cd-resolve-loader!foo.md的字符串。 盖茨比不喜欢那样。 它至少在开发服务器中有效。

其余代码在这里

构建输出是一个简单的组件,具有一组用于子代的静态节点。

var h = require('react').createElement;
var n1 = h('div', { key: 1, dangerouslySetInnerHTML: { __html: '<h1>Hello</h1>' } });
var n2 = h(CustomComponent, { key: 2, foo: 1 });

module.exports = () => h('div', null, [n1, n2]);

呵呵有趣!

不幸的是,据我所知,这也将中断开发中降价促销的重装。

是的,那是另一个问题。 我认为,如果问题得到解决,就捆绑软件的大小和互动时间而言,这将是最好的最终结果之一。 当然,离解决方案还有很长的路要走。 备注工作后如何获得对JS文件的编译的任何提示?

@brigand我认为最简单的解决方案是我在前面的评论中概述的内容https://github.com/gatsbyjs/gatsby/issues/312#issuecomment -336681894

@KyleAMathews对于您提出的解决方案,我们现在知道如何使用remarkjs将包含jsx的markdown转换为html AST 。 我们已经解决了最后一个阻止错误。 现在我们需要创建的代码可以将AST转换为react组件并将其推送到npm。 下周结束之前,我将有一些空闲时间来进行此操作。

如果我那时不推东西,不要犹豫,拿着棒球棍出现在我家门口。

@ r24y得到了这个工作!!! 在使用备注示例站点上查看他的PR https://github.com/gatsbyjs/gatsby/pull/3732和示例页面!

https://using-remark.gatsbyjs.org/custom-components/

因此,在这里报告我的进度。 我有时间完成第二步。

总而言之,我们有两个软件包:
解析为HAST: @ dumpster / remark-custom-element-to-hast
琐碎的渲染成react组件: @ dumpster / hast-react-renderer

@pbellon在这里提出了Gatsby插件

该管道应比重新宣传更为宽松。 如果我没记错的话,rehype使用parser5,它不接受<Note value="my content" />而且我不记得它是否接受自定义元素的主体。

@KyleAMathews我不确定从这里下一步是什么。

@ fazouane-marouane很棒!!!

我认为下一步将是在回购中添加示例网站,以便我们也可以展示您的工作-然后我们需要在gatsbyjs.org上打开一个文档页面,以讨论它们的不同选择和折衷方案。

真好! 感谢您的澄清。

下周或下周(本周一开始新工作job),我会尝试一些东西。

在阅读https://using-remark.gatsbyjs.org/custom-components/并进行尝试之后,我制作了一个名为gatsby-remark-component的小包装,以避免validateDOMNesting警告,如果您的组件位于降价促销中包含块级元素(div ...)。 默认情况下,自定义组件被包装到一个段落中,而与此包一起,它们被包装到一个div中。
很好用

//In your gatsby-config.js
plugins: [
  {
    resolve: "gatsby-transformer-remark",
    options: {
      plugins: [
        {
          resolve: "gatsby-remark-component",
          options: { components: ["my-component", "other-component"] }
        }
      ]
    }
  }
]

我希望这对某人有用。

@Hebilicious感谢您的插件; 是的,我确实意识到所有自定义组件都在<p>元素内呈现,并且我正在使用,

<div>
  <custome-component></custom-component>
</div>

作为解决方法。

但是,将所有自定义组件再次包含到配置文件中并不容易,就像我已经在markdown模板文件中所做的那样。

@ li-xinyang我同意你的看法。 我添加了自动检测功能,因此您不必手动添加它们。
如果要尝试,请确保将软件包升级到最新版本1.1.0
它开箱即用:

//In your gatsby-config.js ...
plugins: [
  {
    resolve: "gatsby-transformer-remark",
    options: {
      plugins: ["gatsby-remark-component"]
    }
  }
]

这有点切线,但这里的人们可能会对与@rauchg协调建议

@ r24y听起来很漂亮!

我认为,可以通过几种折衷方法来解决此问题。

我不知道您是否知道名为Catalog的项目,该项目还支持将React组件嵌入Markdown中。 还有一个名为gatsby-remark-design-system的Gatsby插件,它试图适应Catalog的概念。

这个解决方案看起来很完美@arcticicestudio

目录看起来不错; 而且gatsby-remark-design-system插件很酷,但是它不支持React组件。 我确实认为它做得正确,但是它利用了现有的代码块语法为Markdown添加了更复杂的功能。

正如在该线程中多次讨论的那样,我认为使用现有解析器并不完全是所需的功能。 也许可以代替自由浮动的React元素来更清楚地明确表示复杂的React组件,例如markdown文件可能看起来像:

 #一些标题
 ...等等等等

&lt;Example>
   &lt;Etc />
&lt;/Example>

当我们要渲染嵌入的react元素时,我们将语言指定为react ,并且一个JSX感知解析器将启动并生成可与rehype一起使用的有效AST。 如果我们要使用普通的JavaScript棱镜示例,则只需使用普通的javascript语言。

嗨,大家好,这里的讨论很棒。
我正在使用gatsby-remark-component ,但我有一些问题:

  1. 有没有一种方法可以“自动检测”组件? 这样就不必在组件对象中显式通知我的组件了:
const renderAst = new RehypeReact({
  createElement: React.createElement,
  components: {

  },
}).Compiler
  1. 有没有一种方法可以将某些图像与gatsby-remark-images集成? 我的目标之一是,用户可以添加图片并将其通过props发送到我的组件。 就像是:
    <my-component header-image="[](./image.png)"><my-component>

谢谢!

@ThiagoMiranda是的,(2)太好了! 我的用例是一个图片库:

<gallery>
  <item source="image1.jpg" caption="One"></item>
  <item source="image2.jpg" caption="Two"></item>
</gallery>

Zeit的这种JSX感知markdown解析器看起来很有希望: https :

MDX是CommonMark规范的超集,该规范添加了嵌入式JSX和导入/导出语法。

它建立在备注和重新宣传的基础上,因此在gatsby项目中使用的替代品可能会下降很多

我为mdx编写了插件: https :

很酷,想尝试与盖茨比:)

使用@nhducit的mdx插件,连接MDX页面非常简单!

  1. pages/目录中添加mdx的配置和源。

gatsby-config.js

module.exports = {
  plugins: [
    'gatsby-plugin-mdx',
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        name: 'pages',
        path: `${__dirname}/src/pages/`,
      },
    },
  ],
}
  1. 查询所有markdown文件并为每个文件创建页面。

gatsby-node.js

exports.createPages = ({ graphql, boundActionCreators }) => {
  const { createPage } = boundActionCreators

  return new Promise((resolve, reject) => {
    graphql(`
      { 
        allFile(filter:{extension:{eq:"md"}}) {
          edges {
            node {
              absolutePath
              relativeDirectory
              name
            }
          }
        }
      }
    `).then(result => {
      if (result.errors) {
        return reject(result.errors)
      }

      // Create markdown pages.
      result.data.allFile.edges.forEach(({ node: {
        absolutePath,
        relativeDirectory,
        name
       } }) => {
        createPage({
          path: `/${relativeDirectory}/${name}`,
          component: absolutePath
        })
      })
    })
    .then(resolve)
  })
}
  1. 使用MDX🎉

src/pages/my-markdown-page.md

import MyComponent from '../components/MyComponent'

# Title

_some content_

<MyComponent />

@avigoldman不错! 非常高兴看到您的示例已添加到@nhducit插件的自述文件中。

欢迎@avigoldman公关! 👍

@avigoldman看起来这种方法与frontmatter冲突吗?

@nhducit我会做公关!

@lintonye您能否进一步解释您的意思。 您是指MDX的出口吗?

@lintonye您是否尝试过使用mdx导出? 它似乎等效于mdx: https :

如果我错了,请纠正我,但看来我们需要等待带有更高版本Webpack版本的Gatsby 2.0将备注插件传递给MDX。

cc @KyleAMathews

@avigoldman @nhducit使用导出语法从mdx文件中导出数据时,如何在渲染组件时在UI中访问数据?

同样的问题,目前使用MDX,无法:

  • 将自定义样式应用于降价页面
  • 从命名的mdx导出中将前内容作为pathContext注入
    实际上可以做到这一点,但这需要为每个.md文件创建一个.js文件以导入.md文件,因此它会重复工作。

@slorber在此https :

绝对不理想。 Gatsby V2发布后,我将重新讨论这一点。

嗨,谢谢@avigoldman

我也尝试过在这里https://github.com/nhducit/gatsby-plugin-mdx/issues/13#issuecomment -392334706

似乎您找到了我不必正确提取导出内容的丢失部分:babel-plugin-config-export

您在每个博客帖子页面上创建一个布局,不确定要用这种方式来完成布局还是对盖茨比的性能产生什么样的影响,因为使用Remark的人通常只有一个布局...

将插件发布到NPM怎么样? 这似乎比@nhducit关于frontmatter的可用性更高

另外,... mdx graphql片段从何而来?

关于MDX,他们只是添加了“ MDXProvder”(基于React Context),可能有助于将自定义标签与Gatsby集成,cc @avigoldman

@slorber我创建了一个gatsby-transformer-mdx插件,以便可以查询MDX文件。

我将每个布局都视为页面,将每个MDX文件都视为内容。 因此,布局将获取页面上下文,然后将MDX放入其中(就像您使用remark生成的html一样)。
由于特殊的布局组件将消失,因此在Gatsby V2中将无法使用。

MDXProvider看起来很有希望!

在这里添加我的2¢,由于@avigoldman的gatsby-transformer-mdx,我设法破解了自己的大部分网站(该回购仍在使用Jekyll,将很快更新或添加一个新的回购)使用mdx到Gatsby。

那很棒! 这个周末/即将到来的一周应该有一些时间,使其与Gatsby V2完美搭配。

@avigoldman我无法从您的gatsby-transformer-mdx中html字段(是一个字符串),您的转换器使用什么? 如果不需要在任何地方使用webpack加载程序,它们如何工作?

哦,我刚刚读了上面的评论,窍门是Gatsby v1自动将所有内容包装在布局组件中,因此您使用absolutePath定位MDX文件。 😃感谢您的把戏!

@avigoldman关于Gatsby 2插件的新闻吗? 如果您能给出一个粗略的指导,说明如何在没有Gatsby 2中不再存在的布局组件的情况下进行构建,那也将是很棒的。
谢谢!

我希望我可以以某种方式使用MDX的export default功能,但是传递children以外的任何其他道具似乎都不是ATM。 mdx-js / mdx#187

如果我的PR被合并(mdx-js / mdx#189),我认为我们将能够将MDX与现有的gatsby-plugin-mdx和gatsby-transformer-mdx一起使用。 唯一需要做的更改是在我们端,这是从.mdx文件中导出帖子模板:

src/posts/hello-world.mdx

import Post from '../components/post'

# Hello World

Lorem ipsum.

export default Post

gatsby-node.js

const path = require('path')

exports.createPages = ({ actions }) => {
  actions.createPage({
    path: '/posts/hello-world',
    component: path.join(__dirname, 'src', 'posts', 'hello-world.mdx'),
    context: { /* passed as pageContext */ }
  })
}

src/components/post.js

import React from 'react'
import Layout from './layout'

export default ({ children, pageContext }) => (
  <Layout>
    {children}
  </Layout>
)

我认为这真的很关键。 现在,所有gatsby-remark-*插件都在重新实现一堆可能并且应该在React中的渲染逻辑。 这可以简化很多事情。

@DylanVann取决于。 gatsby-remark-*插件进行了很多构建时转换,如果我们在React中进行这些转换,则意味着将很多JS交付给浏览器。 还有在React中无法做的事情,例如https://www.gatsbyjs.org/packages/gatsby-remark-images/?=remark-image

当然,理想情况下,我们将两个世界都融合在一起。

@KyleAMathews是的,虽然它仍然会首先以静态HTML的形式提供,但这意味着在客户端需要更多的JS。 我认为很多人可能都会在其网站的某些部分运送gatsby-image ,因此在这种情况下,重复就不再是问题。

我确实知道gatsby-remark-*插件中有实用程序。 具体来说,渲染逻辑(目前使用字符串完成)似乎可以在React中完成。

我已经使用htmlAst / rehype-react方法进行了这种工作。

看起来是这样,但是实际上它要复杂得多。 如果您相信自己正在做某事,则可以提出一个重点突出的新课题。

似乎很难解决。 不幸的是,我认为我没有时间执行任何事情或提出建议。 部分使用React自定义组件来制作remark插件的想法肯定可行,我有使用它的代码。

这是由@dylanvann/gatsby-remark-cloudinary从以mp4结尾的降价图像生成的。 这个想法是优化视频(在构建时调整大小,添加海报)。 我想要React中的渲染逻辑。 视频的处理是在另一个功能中完成的,但这是替换节点HTML的一部分。

export const videoHTML = ({
    srcVideo,
    srcVideoPoster,
    base64,
    paddingBottom,
    presentationWidth,
}) =>
    `<cloud-video srcvideo="${srcVideo}" srcvideoposter="${srcVideoPoster}" base64="${base64}" paddingbottom="${paddingBottom}" presentationwidth="${presentationWidth}"></cloud-video>`

然后使用带有rehype-react的自定义组件。

import React from 'react'
import rehypeReact from 'rehype-react'
import CloudVideo from './CloudVideo'

const renderAst = new rehypeReact({
  createElement: React.createElement,
  components: {
    'cloud-video': CloudVideo,
  },
}).Compiler

const Markdown = ({ ast }) => renderAst(ast)

Markdown.propTypes = {
  ast: PropTypes.object,
}

export default Markdown

ast可以从GraphQL中拉出。

因此,此组件适用于SSR和客户端。 无论如何,我知道OSS的情况。 我只是说我认为这将是一个很棒的功能,并且可以减少代码的复杂性,所以如果有人有时间找出更好的解决方案,那将是很棒的。

我并不反对您所说的话,我认为就其本身而言,开始一个良好的讨论会更好,而不是在一个包含60多个评论的繁忙讨论结束时。 😉

我和@avigoldman构建了gatsby-mdx,以容纳雄心勃勃的2.0兼容MDX集成和

目前,启用插件后,默认情况下gatsby .mdx页面可以工作,并且在mdx顶部添加了以下附加功能:

  • 使用和查询经典和JSON样式的前题
  • 为未定义一个的mdx文件定义默认布局

我们还计划针对

  • 先进的图像处理
  • 自定义md和hast插件。
  • 与gatsby-transformer-remark相同的所有字段的兼容性

我们还处于生命周期的早期,因此,如果您遇到任何问题,请告诉我们,我们会完成的:)

@ChristopherBiscardi是要与gatsby-plugin-mdx组合使用还是代替它使用?

@silvenon好像不赞成使用gatsby-plugin-mdx,因此它停止在1.0,而gatsby-mdx将向前推进2.0和更高版本。

@ m-allanson认为现在有了gatsby-mdx可以安全解决此问题?

我想是的,谢谢大家🎉

所以是gatsby-mdx现在要优于rehype-react结合gatsby-transformer-remark所描述这里

如果答案不是明确的肯定,那么有人可以解释这两种方法的优缺点吗?

我认为博客文章的Markdown内的JSX,它更具可预测性,并且警告较少。

我不在盖茨比团队中,但我会说是的,在Markdown中,gatsby-mdx是React的首选方式。

@janosh据我知道的盖茨比-MDX不能取代盖茨比,变压器言论尚未完全
似乎仍然缺少例如gatsby-remark-images和gatsby-remark-copy-linked文件以及其他gatsby-remark插件。
我认为他们正在努力,但不确定目前的状态

但是,如果您不需要这些插件或可以等待,那么我会说是的,至少我会喜欢,对我来说似乎更干净

@CanRau我今天打算将其合并(https://github.com/ChristopherBiscardi/gatsby-mdx/pull/68),以进行合并和发布。 有可能会被一些边缘情况下,我们必须处理,但我会看一些他们今天的投产之前,我合并。

PR的状态是正确应用了gatsby-remark- *插件,但是在gatsby-remark-prismjs插件(当前生成HTML输出)的输出方式上,是由Transformer-remark与mdx来处理的管道。 我认为对gatsby-remark-prismjs之类的插件的支持很重要,但也不是最理想的方法。 在MDX世界中,更好的方法是在MDXProvider中将诸如棱镜反应渲染器之类的元素用作code元素,与使用相比,它具有完全的灵活性并可以控制渲染标记插件来达到类似的效果(并且还允许您与非mdx内容(如.js页面)共享该组件)。

我对复制链接文件和图像处理的工作要更关心,而不是对第一版gatsby-remark- *插件支持的棱镜js更为关心。

听起来很棒@ChristopherBiscardi,尤其是复制链接文件和图像支持,我很乐意提供帮助,但实际上,由于我们实在
也许我可以分享一些反馈,我想我会尝试一些较小的元页面来尝试一下

有趣的是,您正在流媒体上工作。.我对生活很陌生,还不了解如何知道自己何时生活。

如果有时间,我们很乐意在将来的任何时候为您提供帮助,如果您有任何疑问,请随时与我联系:)反馈本身可以帮助很多人,因此,如果您尝试尝试,请务必提出问题!

有趣的是,您正在流媒体上工作。.我对生活很陌生,还不了解如何知道自己何时生活。

我在抽搐频道的底部设置了流时间的“日历”。 我知道如果有人拥有一个抽搐帐户,并且他们跟随我,他们将在我上线时收到通知,但是如果不按日程安排,则可以在此查看。 可以肯定的是,您可以观察是否有帐户。 我对自己进行流式传输有点陌生(现在才做几个星期),因此始终欢迎采用更好的方法来进行此类操作。 我有几个人反复走来走去,闲逛/观看/聊天,这很有趣:)

screen shot 2018-08-28 at 1 17 05 pm

凯知道了,很高兴知道

当遇到任何问题时,我一定会发布问题;)

顺便说一句,自从提到Prism以来,我想补充一点,理想情况下应该直接使用备注/ rehype插件,MDX通过mdPluginshastPlugins选项(可以通过gatsby传递)来支持-mdx)。 可以将@ mapbox / rehype-prism之类的插件添加到hastPlugins ,但是我在mdx-js / mdx#226中修复了一些空格问题,因此一旦合并并发布,语法高亮将是不错的选择去!

是的,完全是。 gatsby-mdx已经支持将备注/ rehype插件传递到mdx核心。 例如,这里是@ mapbox / rehype-prism (我从您最初在@silvenon的一些PR /问题讨论中react-live之类的东西)

gatsby-remark-prismjs和其他gatsby-remark- *插件的支持今天在0.1.1中发布,因此现在在rehype / remark / react-components之间至少有3个语法高亮选项😝

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

totsteps picture totsteps  ·  3评论

ferMartz picture ferMartz  ·  3评论

benstr picture benstr  ·  3评论

KyleAMathews picture KyleAMathews  ·  3评论

ghost picture ghost  ·  3评论