利用 Vue 搭建简单的 markdown 编写环境及代码高亮和目录生成

鑫森的 github
效果
### 代码区的高亮
### 目录的生成
开发流程
- 静态页面的制作
- 静态页面的拆分(Vue 组件实现)
- 渲染好 Markdown 界面
- 目录的生成
静态页面的制作
静态依赖
- Bootstrap
- Jquery
- Popper
组件编写
组件的关系
组件文件的内容
├── App.vue├── assets
│ └── logo.png
├── components
│ ├── markdownBody
│ │ ├── catalog.vue
│ │ ├── content.vue
│ │ ├── markdownBody.vue
│ │ └── preview.vue
│ └── markdownHead.vue
├── main.js
└── utils
└── handler.js
组件通信与状态管理
- 个人感觉使用发布订阅机制可以非常灵活并且不是很熟悉这个机制. 因此强制自己使用这个机制进行 Vue 的组件间通信
通信工具
- pubsub.js- npm i --save-dev pubsub-js
- 导入- import PubSub from 'pubsub-js'
 
- 使用- PubSub.publish('contentChange', content)- 参数说明- contentChange- 发布的消息名称,相当于事件触发
 
- content- 发布消息时的具体内容
- 与事件触发的不同之处就在于此,能够携带信息进行传递
 
 
 
- 参数说明
- PubSub.subscribe('contentChange', cb)- 参数说明- contentChange- 订阅的消息名称,相当于事件监听是监听的事件名称
 
- cb- 回调函数,相当于事件监听是具体的事件操作
- 回调函数有两个参数msg和data
- 订阅的消息的真实内容就在第二个参数data中
 
 
 
- 参数说明
 
 
功能实现
markdown 解析
思路
- 通过订阅事件contentChange, 当编辑器的内容发生变化的时候实时获取 markdown 文本
- 利用showdown库将 markdown 内容进行解析
markdown 解析工具
- showdown.js- npm i --save-dev showdown-js
- 导入- import {showdown} from 'showdown-js'
 
- render- var converter = new showdown.Converter()
- convert.makeHTML('markdown context')
 
 
详细内容请见 markdownPreview 组件的代码)
const contentChangeHandler = (vueComponent, content) => {    PubSub.subscribe('contentChange', (msg, data) => {
        if (vueComponent) {
            vueComponent.content = data
            vueComponent.content = converter.makeHtml(data)
        } else {
            content = data
            content = converter.makeHtml(data)
        }
        if (vueComponent) {
            generateCatlog()
        }
    })
    return content
}
- 这是剥离出来的 markdown 渲染内容
- 由于使用了组件的 data- 函数传入了两个参数- 当在 data 内时- 第一个参数传入空值null或者false
- 第二个参数随意传入一个变量
- 将返回的内容设置为 data
 
- 第一个参数传入空值
- 在订阅消息的回调函数中- 第一个参数传入当前的 Vue 组件, 即this
- 第二个参数此时无效
 
- 第一个参数传入当前的 Vue 组件, 即
 
- 当在 data 内时
 
- 函数传入了两个参数
代码高亮
思路
- 对使用 showdown 渲染出来的代码块直接使用 highlight 的高亮方法即可
代码高亮显示工具
- highlight.js- npm i --save-dev highlight
- 导入- import hljs from 'highlight.js'
- import 'highlight.js/styles/atom-one-dark.css'
 
- highlight- hljs.highlightBlock(element)- 参数说明- element 是需要高亮显示的 dom 元素
- element里的代码块 是要被<pre><code>和</code></pre>包裹的代码块
- 默认可以自动识别, 也可以才<code>标签中通过className来指定具体的高亮策略
 
 
- 参数说明
 
 
<pre>    <code class='python'>
import numpy as np
from matplotlib import pyplot as plt
x = np.arange(0,100,0.01)
y = np.sin(x)
plt.plot(x, y)
plt.show()
    <code>
</pre>
详细内容请见 markdownPreview 组件的代码)
const highlightCode = () => {    const preEl = document.querySelectorAll('pre')
    preEl.forEach((element) => {
        hljs.highlightBlock(element)
    })
}
- 在 markdown 内容解析成功之后直接调用上述函数就能使代码块高亮显示
目录的生成
思路
- 在showdown解析好的 html 中获得所有的 h 标签及内容- 怎么获得呢?
- 想到的方法是通过正则表达式进行获取
 
- 考虑到生成内容之后可以通过锚点快速跳转因此需要设置id- 为了保证 id 是惟一的,所以使用标题的text 作为 id
- 那如果 id 里面有中文怎么办- 通过escape(str)将中文转码
 
- 通过
 
- 最后将数据通过refreshCatlog发布给markdownCatlog组件
- 在组件中使用正则表达式剥离出 标题级别,文本内容和 id 属性
- 利用剥离出来的内容制作h标签,并且在标签中内嵌a标签来达到锚点跳转的效果
- 为了视觉上的效果,不同等级的标签会有不同的缩进
- 为了标签显示的不是很 pussy, 对 h 的大小稍微进行了调整
详细内容请见 markdownCatlog 组件的代码)
const updateHead = (elementArray) => {    elementArray.forEach((element) => {
        element.id = escape(element.innerText)
    })
}
- 设置markdown 解析好的 html 页面里面的h标签 id 值被设置且为题
- 解决了中文的问题
- 只需要通过选择器和遍历执行updateHead函数即可
if (!headInfo) {        return false
    }
    let details = []
    headInfo.forEach((element, index) => {
        element.match(/<h(\d) >(.*)?</g)
        details.push({
            head: RegExp.$1,
            id: RegExp.$2,
            detail: RegExp.$3
        })
    }, this)
    let catlog = ''
    details.forEach((element) => {
        let textSize = parseInt(element.head) + 2
        if (textSize > 6) {
            textSize = 6
        }
        let a = `<h${element.head} style='text-indent: ${element.head}em' class= "h${textSize}"
        ><a href="#${element.id}" class= 'text-white'>${element.detail}</a></h${element.head}>`
        catlog = catlog + a
    }, this)
- headInfo 为refreshCatlog发布过来的消息
- this 指向的是markdownCatlog组件
效果图
代码的高亮
目录的生成
以上是 利用 Vue 搭建简单的 markdown 编写环境及代码高亮和目录生成 的全部内容, 来源链接: utcz.com/z/380877.html








