当前位置: 首页 > 科技观察

Mdx将Markdown带入组件时代

时间:2023-03-12 09:13:47 科技观察

前言在MDX出现之前,当JSX和Markdown混合编写时,Markdown的优势并不存在。通常基于模板字符串方法,这需要大量转义和繁琐的语法。MDX是一种让编写Markdown和JSX更容易、更具表现力的尝试。当你将组件(甚至是动态组件或需要加载数据的组件)与Markdown混合使用时,你会写出更有趣的内容。什么是MDXMDX是一种书写格式,可以让你在Markdown文档中无缝插入JSX代码。您还可以导入组件,例如交互式图表或弹出窗口,并将它们嵌入到内容中。先决条件你应该熟悉markdown语法和JavaScript语法(尤其是JSX)。MDX例子比如官网的一个例子,下面代码import{Chart}from'./snowfall.js'exportconstyear=2018#去年的snowfall{year},降雪量高于平均水平。温暖的春天导致附近的许多河流发生洪水。显示效果effect.png如何使用在create-react-app中,你只需要安装@mdx-js/loader,create-react-app5支持自定义loadersrc/App.jsx/*eslint-disableimport/no-webpack-loader-syntax*/importContentfrom"!@mdx-js/loader!./content.mdx";exportdefaultfunctionApp(){return;}src/content.mdx#你好,世界!这是带有JSX的**markdown**:MDX!如果是webpack项目,只需要添加一个@mdx-js/loader来支持module.exports={module:{//…rules:[//…{test:/\.mdx?$/,使用:[//`babel-loader`是可选的:{loader:"babel-loader",options:{}},{loader:"@mdx-js/loader",/**@type{import('@mdx-js/loader').Options}*/options:{/*jsxImportSource:…,otherOptions…*/},},],},],},};插件支持MDX,也支持插件配置,即原版markdown插件。比如想要markdown支持tables和checkboxLists,可以使用remark-gfm插件;from'rehype-katex'importremarkMathfrom'remark-math'module.exports={module:{//…rules:[//…{test:/\.mdx?$/,use:[//`babel-loader`是可选的:{loader:'babel-loader',options:{}},{loader:'@mdx-js/loader',/**@type{import('@mdx-js/loader').options}*/options:{remarkPlugins:[remarkGfm],rehypePlugins:[rehypeKatex]}}}]}]}}当然也可以支持自定义插件,比如img添加默认样式,限制其最大宽度,href跳转到改开新窗口等,如何写markdown插件可以参考unifiedjs.com默认组件,例如https://beta.reactjs.org/添加了很多自定义组件,代码示例如下:importReactfrom"react";importReactDomfrom"react-dom";importPostfrom"./post.mdx";//假设使用了一个集成exportconstH1=({className,...props}:HeadingProps)=>();constcomponents={h1:H1,};ReactDom.render(,document.querySelector("#root"));MDXprovider为每个文档传递组件很麻烦?我们ImportReactfrom'react'importReactDomfrom'react-dom'importPostfrom'./post.mdx'//假设集成用于编译MDX->JS。import{Heading,/*…*/Table}from'./components/index.js'+import{MDXProvider}from'@mdx-js/react'constcomponents={h1:Heading.H1,//…table:Table}ReactDom.render(-,+++,document.querySelector('#root'))在线运行上面的例子都是构建时运行的,所以让MDX在浏览器中运行,比如以后博客编辑器支持MDX,那么我们的博客文章页面就可以有更多互动比如服务端返回的数据,下面代码是next.js的例子import{useState,useEffect,Fragment}from"react";从“react/jsx-runtime.js”导入*作为运行时;import{compile,run}from"@mdx-js/mdx";exportdefaultfunctionPage({code}){const[mdxModule,setMdxModule]=useState();const内容=mdxModule?mdxModule.default:片段;useEffect(()=>{(async()=>{setMdxModule(awaitrun(code,runtime));})();},[code]);return;}exportasyncfunctiongetStaticProps(){constcode=String(awaitcompile("#hi",{outputFormat:"function-body"/*...otherOptions*/}));return{props:{code}};}实时运行比如:官方playground可以实时运行,左边写代码,右边sidedisplaydocument官方playground最简单的代码如下如下:从“vfile”导入{VFile};从“@mdx-js/mdx”导入{评估,};constvalue='##header'constfile=newVFile({basename:"example.mdx",value});const{default:Result}=awaitevaluate(file,runtime);这个Result是一个react组件,如果你想实现类似的功能,请参考官方github中的editor.client.js总结Markdown深受所有程序员的喜爱。Markdown在标准化、结构化和组件化方面存在缺陷。借助MDX,可以编写具有丰富交互和内容形式的Markdown。希望MDX早日投入,早日投入,更希望MDX的解析在互联网产品中越来越规范。