【前端】react-markdown配置解析

白色玫瑰 程序猿

时间: 2023-07-11 阅读: 1 字数:12297

{}
文章目录react-markdown基本配置同步预览配置MdEditorComponent.jsreducer.jsinitBlogState.jsaction-types.jssync-actions.jsstore.jsremark-Gfm配置syntax-highligh配置rehype-katex和remark-math的配置remark-toc...

文章目录

<a href="#reactmarkdown_7">react-markdown基本配置</a>    <a href="#_23">同步预览配置</a>    
 
  <a href="#MdEditorComponentjs_27">MdEditorComponent.js</a>      <a href="#reducerjs_110">reducer.js</a>      <a href="#initBlogStatejs_123">initBlogState.js</a>      <a href="#actiontypesjs_146">action-types.js</a>      <a href="#syncactionsjs_152">sync-actions.js</a>      <a href="#storejs_158">store.js</a>         <a href="#remarkGfm_176">remark-Gfm配置</a>    <a href="#syntaxhighligh_221">syntax-highligh配置</a>    <a href="#rehypekatexremarkmath_267">rehype-katex和remark-math的配置</a>    <a href="#remarktoc_304">remark-toc的配置</a>    <a href="#rehyperaw_325">rehype-raw的配置</a>    <a href="#_347">个性化组件配置</a>    <a href="#_362">总结</a>      

react-markdown是一款github上开源的适用于react的markdown组件,可以基本实现markdown的功能,且可以根据自己的实际应用定制remark组件。官方给出该组件的好处是:

The two main reasons are that they often rely on dangerouslySetInnerHTML or have bugs with how they handle markdown. react-markdown uses a syntax tree to build the virtual dom which allows for updating only the changing DOM instead of completely overwriting. react-markdown is 100% CommonMark (optionally GFM) compliant and has extensions to support custom syntax.

本文将介绍react-markdown的配置,以及部分实用组件的配置和介绍,包括Katex、syntax-highlighter、Gfm以及TOC。react-markdown的源码和完全介绍请移步https://github.com/remarkjs/react-markdown

react-markdown基本配置

使用npm install react-markdown引入react-markdown包,注意该组件的旧版本和新版本使用配置差别较大,我目前为v7.1.0。

一个简单的hello world:

import React from 'react'
import ReactMarkdown from 'react-markdown'
import ReactDom from 'react-dom'

ReactDom.render(<ReactMarkdown># Hello, *world*!</ReactMarkdown>, document.body)

如此以来,简单的react-markdown就配置好啦!但是这种配置支持的语法较少,如表格、代码高亮、数学公式等均不支持,且无法实现同步预览效果。

同步预览配置

我使用的是redux来控制状态,当然也可以使用dva或者其他方式。

MdEditorComponent.js

import React, { Component } from 'react'
import styles from './MdEditorComponent.module.css'
import { connect } from 'react-redux'
import { editMarkdown } from '../../../redux/sync-actions'
import ReactMarkdownComponent from '../article-component/ReactMarkdownComponent'

const DEFAULT_SIZE = 500 //默认代码块高度

class MdEditorComponent extends Component {
  constructor (props) {
   super(props)
   this.state = {
     textareaHeight: DEFAULT_SIZE
   }
  }

  componentDidMount () {
   window.addEventListener('resize', this.handleResize) //监听resize
  }

  handleResize = e => {

  }

  //修改内容状态
  handleInputMarkdown = e => {
   let previewHeight = this.preview.scrollHeight
   let textareaHeight = e.target.scrollHeight
   let height = Math.max(previewHeight, textareaHeight, DEFAULT_SIZE)
   this.setState({ textareaHeight: height })
   this.props.editMarkdown(e.target.value)
  }

  //当鼠标选中textarea时
  handleKeyPressMarkdown = e => {
   let previewHeight = this.preview.scrollHeight
   let textareaHeight = e.target.scrollHeight
   let height = Math.max(previewHeight, textareaHeight, DEFAULT_SIZE)
   //下面是自定义的特殊按键触发的效果
   if (e.keyCode === 9) {
     e.preventDefault()
     this.props.editMarkdown(this.props.markdown + '\t')
   } else if (e.keyCode === 13)
     return false
   else if (e.keyCode === 17) { //left ctrl
     this.setState({ textareaHeight: height })
   } else if (e.keyCode === 8) { //backspace
     this.setState({ textareaHeight: height })
   } else if (e.keyCode === 192) { // ~
     // e.preventDefault()
   }
  }

  render () {
   return (
     <div className={styles.container} style={{
      height: this.state.textareaHeight //设置默认高度
     }}>
      <div className={styles.input}>
        <textarea style={{ border: '0px' }} spellCheck={false} value={this.props.markdown}
               onKeyDown={this.handleKeyPressMarkdown}
               onChange={this.handleInputMarkdown}/>
      </div>
      <div ref={div => this.preview = div} className={styles.md}>
        <ReactMarkdownComponent content={this.props.markdown}/>
      </div>
     </div>
   )
  }
}

//使用redux来控制状态
MdEditorComponent = connect(
  ({ $BlogState: { mdContent } }) => ({ markdown: mdContent }),
  { editMarkdown }
)(MdEditorComponent)

export default MdEditorComponent

reducer.js

export function $BlogState (state = initBlogState, { data, type }) {
  switch (type) {
   case EDIT_MARKDOWN:
     return { ...state, mdContent: data }
   default:
     return state
  }
}

initBlogState.js

初始的显示内容

export const initBlogState = {
  mdContent: `# Markdown Online Editor
## Subtitle

common content

### Little title

   Code Block
  
### Code Syntax Highlight
~~~js
console.log('hello randyzhang')
~~~
`,
}

action-types.js

export const EDIT_MARKDOWN = 'edit_markdown'

sync-actions.js

export const editMarkdown = data => actionFactory(EDIT_MARKDOWN, data)

store.js

import { applyMiddleware, combineReducers, createStore } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension'
import thunk from 'redux-thunk'
import { $BlogState } from './reducers'

const store = createStore(
  combineReducers({
   $BlogState,
  }),
  composeWithDevTools(applyMiddleware(thunk))
)

export default store

remark-Gfm配置

配置好后即可使用表格、删除线、任务列表、引用等操作。需要使用npm install remark-Gfm引入remark-Gfm包。

import React from 'react'
import ReactMarkdown from 'react-markdown'
import ReactDom from 'react-dom'
import remarkGfm from 'remark-gfm'

const markdown = `A paragraph with *emphasis* and **strong importance**.

> A block quote with ~strikethrough~ and a URL: https://reactjs.org.

* Lists
* [ ] todo
* [x] done

A table:

| a | b |
| - | - |
`

ReactDom.render(
  <ReactMarkdown children={markdown} remarkPlugins={[remarkGfm]} />,
  document.body
)

展示的效果为:

A paragraph with emphasis and strong importance.

A block quote with <sub>strikethrough</sub> and a URL: https://reactjs.org.

Lists <input type="checkbox" class="task-list-item-checkbox" disabled> todo <input type="checkbox" class="task-list-item-checkbox" checked="true" disabled> done

A table:

<table> <thead> <tr> <th>a</th> <th>b</th> </tr> </thead> <tbody></tbody> </table>nn

syntax-highligh配置

使用该组件可以实现代码块的彩色,需要使用npm install react-syntax-hightlighter --save来引入react-syntax-highlighter包。

这里components中间的部分主要是针对输入的代码块语言匹配相应的代码高亮,如果非匹配成功则直接使用code形式展示。

import React from 'react'
import ReactDom from 'react-dom'
import ReactMarkdown from 'react-markdown'
import {Prism as SyntaxHighlighter} from 'react-syntax-highlighter'
import {dark} from 'react-syntax-highlighter/dist/esm/styles/prism'

const markdown = `Here is some JavaScript code:

~~~js
console.log('It works!')
~~~
`

ReactDom.render(
  <ReactMarkdown
   children={markdown}
   components={{
     code({node, inline, className, children, ...props}) {
      const match = /language-(\w+)/.exec(className || '')
      return !inline &amp;&amp; match ? (
        <SyntaxHighlighter
         children={String(children).replace(/\n$/, '')}
         style={dark}
         language={match[1]}
         PreTag="div"
         {...props}
        />
      ) : (
        <code className={className} {...props}>
         {children}
        </code>
      )
     }
   }}
  />,
  document.body
)

rehype-katex和remark-math的配置

使用该组件可以轻松的翻译输入的数学公式,输入npm install remark-math rehype-katex引入相应的包。

注意:需要使用katex.css来展示相应的效果,否则会出现BUG

需要在index.html中添加上下列的话并下载包:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.13.13/dist/katex.min.css" integrity="sha384-RZU/ijkSsFbcmivfdRBQDtwuwVqK7GMOw6IMvKyeWL2K5UAlyp6WonmB8m7Jd0Hn" crossorigin="anonymous">

配置的方法为:

import React from 'react'
import ReactDom from 'react-dom'
import ReactMarkdown from 'react-markdown'
import remarkMath from 'remark-math'
import rehypeKatex from 'rehype-katex'

const markdown = ` L = \frac{1}{2} \rho v^2 S C_L`

ReactDom.render(
  <ReactMarkdown
   children={markdown}
   remarkPlugins={[remarkMath]}
   rehypePlugins={[rehypeKatex]}
  />,
  document.body
)

展示的效果为:

L = 1 2 ρ v 2 S C L L = \frac{1}{2} \rho v^2 S C_L L=21​ρv2SCL​

remark-toc的配置

该配置可以帮你自动生成markdown的目录,仅需要在开头使用## Table of Content,即可以自动生成。

需要使用npm install remark-toc引入该包。

import React from 'react'
import ReactDom from 'react-dom'
import ReactMarkdown from 'react-markdown'
import remarkToc from 'remark-toc'

ReactDom.render(
  <ReactMarkdown
   children={markdown}
   remarkPlugins={[remarkToc]}
  />,
  document.body
)

rehype-raw的配置

如果你trusted environment (you trust the markdown),可以使用该配置使markdown支持HTML。需要使用npm install rehype-raw引入该包。

import React from 'react'
import ReactDom from 'react-dom'
import ReactMarkdown from 'react-markdown'
import rehypeRaw from 'rehype-raw'

const input = `<div class="note">

Some *emphasis* and <strong>strong</strong>!

</div>`

ReactDom.render(
  <ReactMarkdown rehypePlugins={[rehypeRaw]} children={input} />,
  document.body
)

个性化组件配置

有时候我们需要修改一些颜色、大小等,则可以按照一下规则进行修改:

<ReactMarkdown
  components={{
   // Map `h1` (`# heading`) to use `h2`s.
   h1: 'h2',
   // Rewrite `em`s (`*like so*`) to `i` with a red foreground color.
   em: ({node, ...props}) => <i style={{color: 'red'}} {...props} />
  }}
/>

总结

react-markdown作为一款适用于react的markdown组件,使用非常方便,且丰富的remark和rehype可以扩展很多功能,自己也可以定义remark组件,推荐大家来使用。

如果有好的使用方法或者更适合的组件也可以告诉我,互相学习和进步~

原文地址:https://blog.csdn.net/weixin_44589651/article/details/121044772?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168905671116800215055565%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=168905671116800215055565&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-21-121044772-null-null.142^v88^control_2,239^v2^insert_chatgpt&utm_term=markdown

本文章网址:https://www.sjxi.cn/detil/3a6d6a0e94d74e95b036d2f82d38c5c0

最新评论

当前未登陆哦
登陆后才可评论哦

湘ICP备2021009447号

×

(穷逼博主)在线接单

QQ: 1164453243

邮箱: abcdsjx@126.com

前端项目代做
前后端分离
Python 爬虫脚本
Java 后台开发
各种脚本编写
服务器搭建
个人博客搭建
Web 应用开发
Chrome 插件编写
Bug 修复