前言
项目中我们会用到一些 markdown 文件作为文档在页面中展示。基本原理是用 js 去读取解析文件,最后渲染出来。所以我们可以在 webpack 编译的过程中将 markdown 文件编译为 js 模块,然后在页面中直接引入。
在了解 webpack 之后知道,每一个 loader 其实都是一个函数,函数接收资源,进行一定的处理之后输出给下一个 loader。明白了这个基本原理,我们也可以编写一个自己的 loader。
话不多说,进入正题。
代码实现
其中核心库使用了 markdown-it、markdown-it-toc-and-anchor,将 md 文件转为 html 字符串,以及获取 md 内容中的标题目录列表。
创建 markdown-loader.js
文件,代码如下:
const MarkdownIt = require('markdown-it')
const MarkdownItTocAndAnchor = require("markdown-it-toc-and-anchor").default
const markdownIt = new MarkdownIt({
html: true
}).use(MarkdownItTocAndAnchor, {
anchorLink: false
})
module.exports = function (source) {
let tocArray = []
let content = markdownIt.render(source, {
tocCallback (markdown, array, html) {
tocArray = array
}
})
// 最后返回一个 js 对象,包含文本内容和目录列表两个属性
return `export default {
content: \`${content}\`,
tocArray: ${JSON.stringify(tocArray)}
}`
}
假设使用 vue-cli 搭建的项目,可在 vue.config.js
中配置如下:
const path = require('path')
module.exports = {
chainWebpack: config => {
config
.module
.rule('md')
.test(/\.md$/)
.use('markdown-loader')
.loader(path.resolve(__dirname, './markdown-loader.js'))
.end()
}
}
在文件中引入 md 文件,查看打印输出。
import demo from './demo.md'
console.log(demo);
使用
<template>
<div class="doc">
<div class="doc-summary">
<ul class="doc-toc">
<template v-for="(item, i) of tocArray">
<li :class="doc-toc-item" :key="i">{{ item.content }}</li>
</template>
</ul>
</div>
<div class="doc-main">
<section class="doc-content markdown-body" v-html="content"></section>
</div>
</div>
</template>
<script>
import demo from './demo.md'
export default {
data () {
return {
content: '',
tocArray: [],
}
},
created () {
const { content, tocArray } = demo
this.content = content
this.tocArray = tocArray
}
}
</script>
<style lang="scss">
// 使用社区中提供的 github-markdown-css 样式,就可以有和 github 一样的效果了。
// https://github.com/sindresorhus/github-markdown-css
@import './github-markdown.css';
...
</style>
效果如下图所示:
总结
在项目中写一些小工具还是蛮有意思的 😘