[Vue3] MarkDown(md)文件生成html页面分享

分享下如何通过MarkDown(.md)文件直接生成页面内容的方法。

呈现形式

  • 最终实现效果:将写好的xxx.md文件放到项目中,编译,即可通过url访问到,并正确渲染

举个栗子

  1. xxx.md放入/src/pages文件夹中:
/my-vue3-ts-project  
|--- src/
|    |--- pages/
|    |    |--- code-repo-exchange.md      # 将md文件放在这里
|    |--- App.vue
  1. 编译nr dev(即npm/pnpm/yarn run dev),通过domain/code-repo-exchange即可访问:
    url-view.png

戳这里体验实际效果

下面对其实现方式进行说明:

项目环境

Vue3 | VueRouter | Vite | vitesse | Typescript

"dependencies": {
    "vue": "^3.3.10",
    "vue-router": "^4.2.5"
  },

实现方式

接下来我会列出在项目中需要新增的内容,修改点旁的注释如果看不明白可以先跳过。

由于新增的内容技术角度不完全一致,详细解释在后续实现思路里再说明

  1. 安装依赖

下方提到的内容都要添加:

// package.json
"devDependencies": {
    "@unhead/vue": "^1.8.10",                  // vue中给markdown文件添加header
    "github-markdown-css": "^5.5.0",        // markdown通用样式
    "markdown-it-anchor": "^8.6.7",          // 为Markdown标题生成唯一的ID,实现导航
    "markdown-it-highlightjs": "^4.0.1",     // 代码块高亮样式
    "markdown-it-prism": "^2.3.0",            // 代码块高亮样式,和highlightjs功能一致。用一个就行了,我最终没用这个
    "unplugin-vue-markdown": "^0.25.2", // 实现markdown的核心库,内部分装了markdown-it
  },

PS:

  • dependenciesdevDependencies两个文件夹,从实现角度装在哪个文件夹都可以
  • 我的安装工具是ni,原因是我用npm,pnpm,yarn装,要么慢,要么报错。
    也可能项目一开始就是用ni装的,只有ni才比较顺利。
  1. Vite修改配置
    引入Markdown及样式,并修改vuevue router插件
// vite.config.ts

// Markdown related
import Markdown from "unplugin-vue-markdown/vite"
import MarkdownItAnchor from "markdown-it-anchor"
import markdownItHighlightjs from "markdown-it-highlightjs"

export default defineConfig({
  plugins: [
    // Vue为新增,之前Vue是配置在VueMacros中,现在为了md文件,删除了VueMacros的相关配置
    Vue({
      include: [/\.vue$/, /\.md$/], 
    }),
    // 整个Markdown都是新增内容
    Markdown({
      headEnabled: true,
      markdownItOptions: {
        html: true,
        linkify: true,
        typographer: true,
      },
      // A function providing the Markdown It instance gets the ability to apply custom settings/plugins
      markdownItSetup(md) {
        md.use(MarkdownItAnchor)
        md.use(markdownItHighlightjs)
      },
      wrapperClasses: "markdown-body", // markdown-body是一个class类,将和github-markdown-css包对应
    }),
    // 注释所有VueMacros的配置,VueMacros和Vue两个会起冲突
    // 可能在VueMacros里也能实现Markdown,但又是一个技术,而且当前包含的内容还不多,暂时就不管了
    // VueMacros({
    //   defineOptions: false,
    //   defineModels: false,
    //   plugins: {
    //     vue: Vue({
    //       script: {
    //         propsDestructure: true,
    //         defineModel: true,
    //       },
    //     }),
    //   },
    // }),

    // VueRouter需新增配置{ extensions: [".vue", ".md"] }
    // https://github.com/posva/unplugin-vue-router
    VueRouter({ extensions: [".vue", ".md"] }),
})
  1. main.ts 新增
// 以下内容均为样式相关
import { createHead } from "@unhead/vue" 
import "github-markdown-css"
import "highlight.js/styles/default.css"

const head = createHead() 
app.use(head) 
  1. pages中添加*.md文件
/my-vue3-ts-project  
|--- src/
|    |--- pages/
|    |    |--- code-repo-exchange.md      # 将md文件放在这里
|    |--- App.vue

4.1 在当前组件中渲染Markdown

<script setup>
import HelloWorld from "~/pages/code-repo-exchange.md"
</script>

<template>
  <HelloWorld class="markdown-body" />
</template>

上面这几部即所有修改内容,完成后应该就能成功。

实现思路

为了实现以上效果,需要集成3个主要技术到项目中:


mind.png

1. markdown核心

unplugin-vue-markdown

这个库是实现markdown的核心库,帮助vue封装markdown-it。
markdown-it是一项更泛用的技术,是一个用于解析和转换 Markdown 文档的 JavaScript 库,适用于其他JavasSript框架(包含nodejs)场景。
unplugin-vueVue官方团队大佬的作品啦,品质有保证。

2. markdown样式

样式是单独引入的。一开始我以为markdown-it已经足够了,但其实并不包含样式,这点在markdown核心提到的相关文档中也没有明确提到,所以一开始走了写弯路。

  • github-markdown-css
  • markdown-it-prism
  • markdown-it-anchor
  • markdown-it-highlightjs

这4个库为markdown进行解析,提供渲染形式的样式库。没有这几个库的话,markdown-it只会渲染到页面上一些平平的文字,并没有字体大小或颜色高亮。

重点在下面这行配置

// vite.config.ts
export default defineConfig({
  plugins: [
    Markdown({
      // Class names for the wrapper div
      wrapperClasses: "markdown-body", // markdown-body是一个class类,将和github-markdown-css包对应
    })
]})

上文中的这个markdown-body,会伴随整个markdown文档加载到DOM的class中,但并没有为其定义具体的css样式。

markdown-class.png

于是再查找资料后,发现要引入github-markdown-cssmarkdown-it-highlightjs,从而才能渲染。
github-markdown-css提供文档样式,markdown-it-highlightjs则对代码样式进行加强。

同时,markdown-it-highlightjs是为vue框架而编写的,本身基于vanillar

3. VueRouter扩展

VueRouter本身是不会引入*.md的,好在vitesse足够强大,稍微修改就能加入。
需要注意的是,以下内容和和unplugin-vue-markdownGit主页修改方式不同。

// vite.config.ts
export default defineConfig({
  plugins: [
    // 注释所有VueMacros的配置,VueMacros和Vue两个会起冲突,导致编译过不去
    // 可能在VueMacros里也能实现Markdown,但又是一个技术,而且当前包含的内容还不多,暂时就不管了
    // VueMacros({
    //   defineOptions: false,
    //   defineModels: false,
    //   plugins: {
    //     vue: Vue({
    //       script: {
    //         propsDestructure: true,
    //         defineModel: true,
    //       },
    //     }),
    //   },
    // }),

    // VueRouter需新增配置{ extensions: [".vue", ".md"] }
    // https://github.com/posva/unplugin-vue-router
    VueRouter({ extensions: [".vue", ".md"] }),
})

Git主页是这样的:

import Vue from '@vitejs/plugin-vue'
import Markdown from 'unplugin-vue-markdown/vite'
import Pages from 'vite-plugin-pages'

export default {
  plugins: [
    Vue({
      include: [/\.vue$/, /\.md$/],
    }),
    Pages({
      extensions: ['vue', 'md'],
    }),
    Markdown()
  ],
}

上图中有两个不同:

  1. VueMacros配置删除。VueMacros基于unplugin-vue-macros库,但因为和Vue节点会产生冲突,具体原因还不清楚,文档内容有些多我就没有继续深究。
  2. VueRouter({ extensions: [".vue", ".md"] })修改,基于unplugin-vue-router库。和官网指引的库vite-plugin-pages写法也有不同,
  3. unplugin-vue-router配置详见Github主页

我的项目本身基于vitesse-lite,可能有更优雅的解法。

  • @unhead/vue: 这个库是为了给*.md加上<head>头,但目前我项目里还没用上

总结

要方便得将Markdown引入到项目中,上述三点(Markdown核心,Markdown样式,VueRouter扩展)缺一不可。实现起来不算简单,但一旦实现以后,对于项目来说是非常方便的,尤其适合个人网站的项目,可以通过Markdown快速排版并进行发布,非常节省时间精力。

后续计划对md的seo再进行学习。

附录

体验地址
项目base->vitesse-lite
unplugin-vue-router
unplugin-vue-markdown
antfu大佬个人网站

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容