vue3解析markdown文件为html并且高亮显示代码块

news2025/3/11 11:26:59

前言:

很多时候我们程序员写的文档都是以markdown为主,但是我们每次找相关资料极为不便,如果能直接把markdown文档引进vue项目里,解析成html并且展示出来,然后部署在服务器上,查看是不是极为方便呢。(在做公司的私有组件库的时候,每一个组件都有一个README.md,我们在代码里查看并不方便,何不在展示组件的时候,把对应的README.md的也引进来解析出来,边看效果,边看文档多香啊)。

安装插件:

需要安装marked 和highlight.js两种插件

npm i marked highlight.js -D

编写mdToJs.js,用于将markdown文档转化为js

以下代码可直接复制应用

import path from "path";
import fs from "fs";
import { marked } from "marked";

const mdToJs = (str) => {
  const content = JSON.stringify(marked(str));
  return `export default ${content}`;
};

export function md() {
  return {
    name: "md",
    configureServer() {
      // 用于开发
      async ({ app }) => {
        app.use(async (ctx, next) => {
          // koa
          if (ctx.path.endsWith(".md")) {
            ctx.type = "js";
            const filePath = path.join(process.cwd(), ctx.path);
            ctx.body = mdToJs(fs.readFileSync(filePath).toString());
          } else {
            await next();
          }
        });
      };
    },
    transform(code, id) {
      // 用于 rollup // 插件
      // 获取文件后缀名
      const fileArr = id.split("."); //根据.分割数组
      const fileType = fileArr[fileArr.length - 1]; //取最后一个

      if (/\md$/.test(fileType)) {
        return mdToJs(code);
      }
      return;
    },
  };
}

配置vite.config.js

引入上面的md.js,在plugins里注入调用

import { fileURLToPath, URL } from "node:url";

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { md } from "./mdToJs";

// https://vitejs.dev/config/
export default defineConfig({
  base: "/",
  server: {
    open: true,
    hmr: true,
  },
  plugins: [vue(), md()],
  resolve: {
    alias: {
      "@": fileURLToPath(new URL("./src", import.meta.url)),
    },
  },
});

到这里,项目里已经可以正常引入md文档,不报错了

我们来看看效果

因为解析成js,所以我们渲染的时候,需要用v-html来渲染

<template>
  <div>MD</div>
  <article v-html="MDFile" />
</template>

<script setup>
import MDFile from "./assets/README.md";
</script>

 我们可以看到,代码块是没有高亮显示的

接下来,我们将会借助highlight.js进行高亮显示代码块

高亮显示

写一个自定义hooks,然后在需要高亮的页面里调用这个hooks

src/hooks/md.js

下面的hooks可以直接复制到项目里用

import { onMounted } from "vue";
import hljs from "highlight.js"; // 引入 highlight.js

export function useHighLight() {
  const handleHighLight = () => {
    let blocks = document.querySelectorAll("pre code");
    blocks.forEach((block) => {
      hljs.highlightBlock(block);
    });
  };

  onMounted(() => {
    handleHighLight();
  });
}

 highlight.js事实上提供了很多种主题的高亮样式,我们看一下node_modules里

 我们选择其中一种引入到全局里就好

main.js

// import './assets/main.css'
import { createApp } from "vue";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import App from "./App.vue";
//引入highlight.js其中一种主题样式
import "highlight.js/styles/monokai-sublime.css"; 

const app = createApp(App);

app.use(ElementPlus);
app.mount("#app");

在需要高亮显示代码块的页面里调用上面的hooks

<template>
  <div>MD</div>
  <article v-html="MDFile" />
</template>

<script setup>
import MDFile from "./assets/README.md";
import { useHighLight } from '../src/hooks/md'

useHighLight()
</script>

再看一下效果

md解析完成,高亮显示代码块完成~


拓展:

下面是一些其他方面的心得,感兴趣的可以看下。

事实上,我们在plugins注入的md函数将markdown转化为js。还有其他方式,比如可以把markdown转化为vue。让我们来看下如何运用

编写mdToVue.js将markdown转化为vue

/*
 * @Description:
 * @Author: yangxiao
 * @Date: 2024-04-10 13:20:15
 * @LastEditTime: 2024-04-12 11:16:23
 * @LastEditors: yangxiao
 */
import { marked} from 'marked'

export default function (options) {
  return {
    name: 'vitePluginMd2Vue',
    transform(src, id) {
      /**
      * id是导入的文件路径
      * src是导入的文件内容
      */
      if (id.endsWith(".md")) { // 判断结尾字符串判断是否为markdown文件

        return {
          // code中使用sfc会导致没有走vite的解析流程,所以直接使用渲染函数编写
          code: `import {h, defineComponent} from "vue";
                const _sfc_md = defineComponent({
                    name: "Markdown",
                });

                const _sfc_render =() => {
                    return h("div", {
                      innerHTML: ${JSON.stringify(marked(src))},
                    })
                };

                _sfc_md.render = _sfc_render
                export default _sfc_md`, // code是转换后最终输出的代码
          map: null  // 是否提供source map,这里可以不用考虑
        }
      }
    }
  }
}

在vite.config.js的plugins里注入调用

import { fileURLToPath, URL } from "node:url";

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import mdToVue from './examples/plugin/mdToVue.js'

// https://vitejs.dev/config/
export default defineConfig({
  base: "/",
  server: {
    open: true,
    hmr: true,
  },
  plugins: [vue(), mdToVue()],
  resolve: {
    alias: {
      "@": fileURLToPath(new URL("./src", import.meta.url)),
    },
  },
});

这个时候我们可以直接在页面里引入markdown文件,解析成html进行展示

<template>
  <div>MD</div>
  <MDFile/>
</template>

<script setup>
import MDFile from "./assets/README.md";
</script>

高亮的相关配置和上面的没有区别~

高亮随机主题色

我们从上面的node_modules的截图里可以看到,事实上,highlight.js提供了很多种高亮样式主题,我们只用一种未免过于单调,所以笔者呢,挑了10种,做了个随机代码高亮主题

编写一个mdCodeTheme.js用于存放随机高亮主题的代码

@/utils/mdCodeTheme.js

function getRandomInt() {
  return Math.floor(Math.random() * 10) + 1;
}

switch (getRandomInt()) {
  case 1:
    import("highlight.js/styles/devibeans.css");
    break;
  case 2:
    import("highlight.js/styles/a11y-dark.css");
    break;
  case 3:
    import("highlight.js/styles/agate.css");
    break;
  case 4:
    import("highlight.js/styles/an-old-hope.css");
    break;
  case 5:
    import("highlight.js/styles/androidstudio.css");
    break;
  case 6:
    import("highlight.js/styles/felipec.css");
    break;
  case 7:
    import("highlight.js/styles/arta.css");
    break;
  case 8:
    import("highlight.js/styles/github-dark-dimmed.css");
    break;
  case 9:
    import("highlight.js/styles/atom-one-dark-reasonable.css");
    break;
  case 10:
    import("highlight.js/styles/monokai-sublime.css");
    break;
}

然后把上面的mdCodeTheme.js引入到main.js里就好

// import './assets/main.css'
import { createApp } from "vue";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import App from "./App.vue";
import './src/utils/mdCodeTheme'

const app = createApp(App);

app.use(ElementPlus);
app.mount("#app");

这样就能每次进入项目的时候随机切换主题色啦~

手动切换高亮主题色

这里提供一个思路吧,就不再进行代码演示了。

在header区域加一个下拉框。然后写死一个数据源,给每一个主题色标上序号,切换主题色的时候,把对应的序号存到localStorage里,然后强制刷新页面(window.location.reload())。重新进入项目的时候。main.js里判断localStorage里存没存高亮主题色的序号,如果有,就懒加载对应的主题色css。如果没有,就显示默认的主题色。这样就实现手动切换主题色啦~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1968926.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3D打印随形透气钢:模具困气终结者

困气是模具经常遇到的问题&#xff0c;是制约生产效率与产品质量的关键因素之一。传统透气钢材料虽有所助益&#xff0c;但其在加工复杂度、形状适应性及性能均衡性上的局限性明显。在此背景下&#xff0c;3D打印技术的革新性应用——随形透气钢应运而生&#xff0c;为困气、排…

view 和 reshape的区别 及 测试对一个数据执行view 和 reshape之后得到的数据还一样吗

一、测试对一个数据执行view 和 reshape之后得到的数据还一样吗 问题&#xff1a; x torch.randn(2, 3, 4) y_view x.view(12&#xff0c; 2) y_reshape y_view.reshape(2&#xff0c;3, 4)得到的结果一样吗 import torch# 创建一个张量 x torch.randn(2, 3, 4)# 使用 …

Datawhale夏令营AI for Science(AI+气象)学习笔记1

如何针对降水预测问题搭建模型 回顾baseline, 我们可以大致将搭建模型并解决问题分为以下几个步骤: 定义数据集, 建立起训练数据和标签之间的关系&#xff1b;定义数据加载器(DataLoader)&#xff0c; 方便取数据进行训练 定义模型, 利用PyTorch搭建网络&#xff0c;根据输入…

关于DynamoRIO处理多线程程序时候的问题

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

【天机学堂】面试总结

写在前面&#xff0c;首先要将天机学堂包装一下&#xff0c;智慧教育平台》&#xff0c;暂时就想到这个。天机学堂文档 1.包装简历 待更新。。。

持续集成09--Jenkins配置Sonar代码漏洞扫描工具

专栏内容 持续集成01--Git版本管理及基础应用实践_持续集成下的git分支-CSDN博客 持续集成02--Linux环境更新/安装Java新版本-CSDN博客 持续集成03--Jenkins的安装与配置-CSDN博客 持续集成04--Jenkins结合Gitee创建项目_jenkins集成gitee-CSDN博客 持续集成05--Gogs的安装与使…

Ubuntu运行深度学习代码,代码随机epoch中断没有任何报错

深度学习运行代码直接中断 文章目录 深度学习运行代码直接中断问题描述设备信息问题补充解决思路问题发现及正确解决思路新问题出现最终问题&#xff1a;ubuntu系统&#xff0c;4090显卡安装英伟达驱动535.x外的驱动会导致开机无法进入桌面问题记录 问题描述 运行深度学习代码…

MySQL--表完整性约束

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 作用&#xff1a;用于保证数据的完整性和一致性 约束条件说明PRIMARY KEY (PK)该字段为该表的主键&#xff0c;可以唯一的标识记录&#xff0c;不可以…

【Python 逆向滑块】(实战三)逆向滑块,并实现用Python+Node.js 生成滑块、识别滑块、验证滑块、发送短信

逆向日期&#xff1a;2024.08.01 使用工具&#xff1a;Node.js 本章知识&#xff1a;逆向网易易盾【cb】参数 文章难度&#xff1a;中等&#xff08;没耐心的请离开&#xff09; 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要做的可联系我】 AES解密处理…

乐鑫ESP32-S3语音唤醒和命令词识别,XIAO ESP32 S3 Sense开发套件应用

在这个数字化飞速发展的时代&#xff0c;小型化、智能化已成为技术发展的趋势。ESP32-S3芯片在物联网和嵌入式机器学习领域的应用潜力&#xff0c;让我们对智能设备的未来充满了无限遐想。 OpenGlass项目中的Seeed Studio XIAO ESP32 S3 Sense开发套件&#xff0c;以其小巧的体…

【kali靶机之serial】--反序列化漏洞实操

kali靶机配置 【我图片里没有截图的默认配置即可】需要改的地方图片里面都有。 使用kali扫描网关的主机。 扫到一个开放了80端口HTTP协议的主机ip 访问80端口 会看到一个文本页面&#xff0c;翻译一下看是什么意思。。 F12查看cookie&#xff0c;是一个base64编码了的东西 使…

再获奖项,亚信安慧AntDB数据库被评为“2023-2024国产数据库创新赋能优秀产品”

日前&#xff0c;由工业和信息化部直属的中国电子信息产业发展研究院赛迪网、《数字经济》杂志主办的第二届数字驱动创新峰会&#xff08;DDIS 2024&#xff09;在京隆重举办&#xff0c;“2023-2024数字创新优秀成果案例” 征集结果同期正式发布。亚信安慧AntDB数据库凭借多年…

「9月·张家口」第二届机器视觉、图像处理与影像技术国际会议(MVIPIT 2024)

第二届机器视觉、图像处理与影像技术国际会议(MVIPIT 2024)将于2024年9月13日-15日在中国张家口召开。MVIPIT 2024聚焦机器视觉、图像处理与影像技术&#xff0c;旨在为专家、学者和研究人员提供一个国际平台&#xff0c;分享研究成果&#xff0c;讨论问题和挑战&#xff0c;探…

ARM架构中的Cache stashing介绍

快速链接: . 👉👉👉 ARMv8/ARMv9架构入门到精通-[目录] 👈👈👈 付费专栏-付费课程 【购买须知】:个人博客笔记导读目录(全部) Reliability, Availability, and I/O coherent Requesting Node (RN-I)I/O coherent Requesting Node with DVM support (RN-D)Fully c…

【C#工具类】Excel接口(一)

目录 需求描述 具体需求分析 学习交流&#xff08;Bug待解决&#xff09; Debug代码&#xff08;写代码的过程&#xff0c;逐渐完善的过程&#xff09; 参考资料 扩展阅读 需求描述 用C#生成两个函数 1. 盲读Excel (Excel文件名) 读取所有单元格的数据&#xff0c;并输…

什么是IO多路复用?其原理和用途是什么?

什么是IO&#xff1f; IO&#xff1a;Input/Output&#xff0c;即数据的读取&#xff08;接收&#xff09;/写入&#xff08;发送&#xff09;操作&#xff0c;针对不同的数据存储媒介&#xff0c;大致可以分为网络 IO 和磁盘 IO 两种。在 Linux 系统中&#xff0c;为了保证系…

计算机毕业设计Hadoop+Hive专利分析可视化 面向专利的大数据管理系统 专利爬虫 专利数据分析 大数据毕业设计 Spark

《Hadoop专利大数据分析可视化系统》开题报告 一、选题背景与意义 随着信息技术的飞速发展&#xff0c;全球数据量呈现爆炸式增长&#xff0c;特别是在专利领域&#xff0c;数据的积累和更新速度更是惊人。专利数据不仅包含了技术创新的详细信息&#xff0c;还反映了行业的发…

Java数据结构(五)——栈和队列

文章目录 栈和队列栈基本概念栈的模拟实现集合框架中的栈栈的创建栈的方法栈的遍历 栈的应用及相关练习括号匹配逆波兰表达式求值出栈入栈次序匹配最小栈 几个含"栈"概念的区分 队列基本概念队列的模拟实现循环队列双端队列集合框架中的队列队列的创建队列的方法队列…

嵌入式day16

结构体与共用体 概述 通常结构体名第一个字符大写 } &#xff1b; 分号不能省略 类型名与变量名的关系 &#xff1a;抽象与具体的关系 . &#xff1a;结构体成员运算符 先有类型&#xff0c;再有定义 Student 可省略 使用者只能用全局变量s1&#xff0c;s2 全部初始化&am…

Redis缓存常见问题

Redis 缓存的穿透、雪崩、击穿是三种常见的问题&#xff0c;它们各自的表现和应对策略有所不同。以下是这三者的区别&#xff1a; 1. 缓存穿透&#xff08;Cache Penetration&#xff09; 现象: 缓存穿透是指客户端请求的数据在缓存中不存在&#xff0c;同时在数据库中也不存…