P17:利用marked+highlight.js重构前台文章详细页面
之前我们在博客文章详细页使用了react-markdown
模块,但是这个插件的配置项还是太少了,而且我也没做太多的技术调研,所以我决定转回我目前项目中使用的一套方案marked+highlight.js
。这个方案是比较成熟的,目前公司的开发文档程序就是基于这个开发的。
安装 marked 和 highlight.js
这两个模块需要先安装,这里我们就使用npm
来进行安装。打开终端,进入到blog
目录下,然后使用下面命令进行安装。
npm install --save marked npm install --save highlight.js
当然也可使用yarn
来进行安装
yarn add marked yarn add highlight.js
我目前的版本是 marked 是 1.2.5,highlight 是 10.4.0。如果版本有变化,导致代码没法运行,可自行查看 API 进行修改。
重构detailed.js文件
这里的重构主要就是替换以前的Markdown
解决方案。在代码顶部用import
引入刚才安装的marked
和highlight.js
。
引入模块
import marked from 'marked' import hljs from "highlight.js"; import 'highlight.js/styles/monokai-sublime.css';
引入设置一下marked.setOptions
,里边的属性比较多,我在这里详细的介绍一下。
const renderer = new marked.Renderer(); marked.setOptions({ renderer: renderer, gfm: true, pedantic: false, sanitize: false, tables: true, breaks: false, smartLists: true, smartypants: false, highlight: function (code) { return hljs.highlightAuto(code).value; } }); let html = marked(props.article_content);
- gfm:启动类似 Github 样式的 Markdown,填写 true 或者 false
- pedatic:只解析符合 Markdown 定义的,不修正 Markdown 的错误。填写 true 或者 false
- sanitize: 原始输出,忽略 HTML 标签,这个作为一个开发人员,一定要写 flase
- tables: 支持 Github 形式的表格,必须打开 gfm 选项
- breaks: 支持 Github 换行符,必须打开 gfm 选项,填写 true 或者 false
- smartLists:优化列表输出,这个填写 ture 之后,你的样式会好看很多,所以建议设置成 ture
- highlight: 高亮显示规则 ,这里我们将使用 highlight.js 来完成
增加 Code 的高亮显示
在设置setOptions
属性时,可以直接设置高亮显示,代码如下:
highlight: function (code) { return hljs.highlightAuto(code).value; }
设置完成后,你在浏览器检查代码时就可以出现 hljs 的样式,说明你的效果加成功了,实现了高亮显示代码。
detailed.js 所有代码
import React,{useState} from 'react' import Head from 'next/head' import axios from 'axios' import {Row, Col, Space, Breadcrumb, Affix} from 'antd' import {ClockCircleOutlined,VideoCameraOutlined,FireOutlined} from '@ant-design/icons' import MarkNav from 'markdown-navbar'; import 'markdown-navbar/dist/navbar.css'; import marked from 'marked' import hljs from "highlight.js"; import 'highlight.js/styles/monokai-sublime.css'; import Header from '../components/Header' import Author from '../components/Author' import Advert from '../components/Advert' import Footer from '../components/Footer' const Detailed = (props) => { const IconText = ({ icon, text }) => ( <Space> {React.createElement(icon)} {text} </Space> ); const renderer = new marked.Renderer(); marked.setOptions({ renderer: renderer, gfm: true, pedantic: false, sanitize: false, tables: true, breaks: false, smartLists: true, smartypants: false, highlight: function (code) { return hljs.highlightAuto(code).value; } }); let html = marked(props.article_content); return ( <> <Head> <title>博客详细页</title> </Head> <Header /> <Row className="comm-main" type="flex" justify="center"> <Col className="comm-left" xs={24} sm={24} md={16} lg={18} xl={14} > <div> <div className="bread-div"> <Breadcrumb> <Breadcrumb.Item><a href="/">首页</a></Breadcrumb.Item> <Breadcrumb.Item>教程列表</Breadcrumb.Item> <Breadcrumb.Item>xxxx</Breadcrumb.Item> </Breadcrumb> </div> <div> <div className="detailed-title"> React 实战教程笔记-码云笔记开发 </div> <div className="list-icon center"> <IconText icon={ClockCircleOutlined} text="2020-12-01" key="list-vertical-star-o" /> <IconText icon={VideoCameraOutlined} text="前端教程" key="list-vertical-like-o" /> <IconText icon={FireOutlined} text="5498 人" key="list-vertical-message" /> </div> <div className="detailed-content" dangerouslySetInnerHTML={{__html:html}} > </div> </div> </div> </Col> <Col className="comm-right" xs={0} sm={0} md={7} lg={5} xl={4}> <Author /> <Advert /> <Affix offsetTop={5}> <div className="detailed-nav comm-box"> <div className="nav-title">文章目录</div> <MarkNav className="article-menu" source={html} ordered={false} /> </div> </Affix> </Col> </Row> <Footer/> </> ) } Detailed.getInitialProps = async(context) => { let id = context.query.id; const promise = new Promise((resolve)=>{ axios('http://127.0.0.1:7001/default/getArticleById/' + id).then((res) => { console.log(res) resolve(res.data.data[0]) }) }) return await promise } export default Detailed
CSS 样式的更换
都设置好以后,是不是又觉的现在样式也不是很好看,所以可以继续设置一下 CSS 样式。因为笔记中我不讲解 CSS 样式部分,但是我给你提供了我detailed.css
所有代码
.bread-div{ padding: .5rem; border-bottom:1px solid #eee; background-color: #e1f0ff; } .detailed-title{ font-size: 1.8rem; text-align: center; padding: 1rem; } .center{ text-align: center; } .detailed-content{ padding: 1.3rem; font-size: 1rem; } pre{ display: block; background-color:#f3f3f3; padding: .5rem !important; overflow-y: auto; font-weight: 300; font-family: Menlo, monospace; border-radius: .3rem; } pre{ background-color: #283646 !important; } pre >code{ border:0px !important; background-color: #283646 !important; color:#FFF; } code { display: inline-block ; background-color:#f3f3f3; border:1px solid #fdb9cc; border-radius:3px; font-size: 12px; padding-left: 5px; padding-right: 5px; color:#4f4f4f; margin: 0px 3px; } .title-anchor{ color:#888 !important; padding:4px !important; margin: 0rem !important; height: auto !important; line-height: 1.2rem !important; font-size: .7rem !important; border-bottom: 1px dashed #eee; overflow: hidden; text-overflow:ellipsis; white-space: nowrap; } .active{ color:rgb(30, 144, 255) !important; } .nav-title{ text-align: center; color: #888; border-bottom: 1px solid rgb(30, 144, 255); } .article-menu{ font-size:12px; } iframe{ height: 34rem; } .detailed-content img{ width: 100%; border:1px solid #f3f3f3; } .title-level3{ display: none !important; } .ant-anchor-link-title{ font-size: 12px !important; } .ant-anchor-wrapper{ padding: 5px !important; }
样式复制完,我们再到浏览器中预览一下,应该就可以出现更漂亮的效果了。
本文内容就到这里,下节我们把右侧的导航也重新完善一下,实现对文章章节的导航效果。学习是一定要跟着作,如果不作你也许什么都学不会。
码云笔记 » P17:利用marked+highlight.js重构前台文章详细页面