React博客项目系列1 编写markdown文章,代码高亮,显示文章与目录

在掘金发完来csdn发,一🐟两吃了属于是😀,以下是正文。

最近在学React,想着做个博客项目练练手,学到了很多东西,在此记录一下。

下载依赖

// markdown编辑器
yarn add for-editor
// 用于显示markdown文章
yarn add react-markdown
// 用于显示目录,不过显示有bug,可以先不下载看后面
yarn add markdown-navbar
// 划线、表、任务列表和直接url等的语法扩展
yarn add remark-gfm   
// 解析标签,支持html语法
yarn add rehype-raw   
// markdown内容样式,也可以自己写
yarn add github-markdown-css
// 用于高亮代码块
yarn add react-syntax-highlighter

编写markdown文章

for-editor

import Editor from 'for-editor'
import { useState } from 'react'
const EditArticle = () => {
  // 编辑器配置,可以根据自己需要决定是否显示
  const toolbar = {
    h1: true, // h1
    h2: true, // h2
    h3: true, // h3
    h4: true, // h4
    img: true, // 图片
    link: true, // 链接
    code: true, // 代码块
    preview: true, // 预览
    expand: true, // 全屏
    /* v0.0.9 */
    undo: true, // 撤销
    redo: true, // 重做
    save: true, // 保存
    /* v0.2.3 */
    subfield: true, // 单双栏模式
  }
  // 文章内容
  const [value, setValue] = useState('')
  const handleChange = (val) => {
    setValue(val)
  }
  return (
    <div className='editor-box container has-nav'>    
      <div className='main'>
        <Editor className="editor" toolbar={toolbar} value={value} onChange={handleChange} preview={true} subfield={true} />
      </div>
    </div >
  )
}
export default EditArticle

效果:
image.png

显示markdown文章及代码高亮

react-markdown

react-syntax-highlighter

在这里预览代码高亮效果

github-markdown.css

import { useState, useEffect } from 'react'
// 文章显示
import ReactMarkdown from 'react-markdown'
// 划线、表、任务列表和直接url等的语法扩展
import remarkGfm from 'remark-gfm'
// 解析标签,支持html语法
import rehypeRaw from 'rehype-raw'
// 代码高亮
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
// 高亮的主题
import { coldarkDark } from 'react-syntax-highlighter/dist/esm/styles/prism'
// 这里我想方便修改样式,所以没有yarn add github-markdown-css而是直接把这个样式文件放在文件夹里了
import '@/styles/githubMarkdown.css'
const ArticleDetail = () => {
  // 这是通过接口拿到的文章
  const [articleMsg, setArticleMsg] = useState({})
  return (
    <div className='article-detail has-nav flex'>
      <div className='left-box flex-sub'>
        <div className='article-box bg-white'>
          <div className='article-body'>
            <ReactMarkdown
              // 使用github-markdown-css样式的话className必须是markdown-body
              className='markdown-body'
              // 插件及选项,singleTilde: false表示单波浪线也可以作为擦除线,但我设置true或false都没变化
              remarkPlugins={[remarkGfm, { singleTilde: false }]}
              rehypePlugins={[rehypeRaw]}
              components={{
                // 代码高亮
                code ({ node, inline, className, children, ...props }) {
                  const match = /language-(\w+)/.exec(className || '')
                  return !inline && match ? (
                    <SyntaxHighlighter
                      children={String(children).replace(/\n$/, '')}
                      style={coldarkDark}
                      language={match[1]}
                      PreTag="div"
                      showLineNumbers={true}
                      {...props}
                    />
                  ) : (
                    <code className={className} {...props} children={children} />
                  )
                }
              }}
            >{articleMsg.body}</ReactMarkdown>
          </div>
        </div>
      </div>
    </div>
  )
}
export default ArticleDetail

效果:

image.png

样式换成掘金的康康🤣:

image.png

显示目录

markdown-navbar

markdown-navbar很好用,但是有时标题显示会有问题:

image.png

bug修复

bug修复

image.png

我的做法是把文件直接拷贝到项目里改完后再引入

import { useState, useEffect } from 'react'
// 有bug所以把文件拷贝在本地自己修改了
import MarkdownNavbar from '@/components/markdownNavbar'
const ArticleDetail = () => {
  // 这是通过接口拿到的文章
  const [articleMsg, setArticleMsg] = useState({})
  return (
    <div className='article-detail has-nav flex'>
      <div className='article-content basis-xs xs-hide flex'>
        <div className='markdown-nav content-sticky bg-white ellipsis'>
          <div className='sidebar-title'><span>目录</span></div>
          <MarkdownNavbar
            className="md-navbar"
            source={articleMsg.body}
            headingTopOffset={80}
            ordered={false} />
        </div>
      </div>
    </div>
   </div>
  )
}
export default ArticleDetail

修复后:

image.png

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值