当前位置: 首页 > news >正文

记一次使用vue-markdown在vue中解析markdown格式文件,并自动生成目录大纲

先上效果图

如图所示,在网页中,能直接解析markdown文档,并且生成目录大纲,也支持点击目录标题跳转到对应栏目中,下面就来讲讲是如何实现此功能的。

1、下载vue-markdown

yarn add vue-markdown

2、在页面中渲染markdown文件

<template><div><VueMarkdownclass="api-content":source="markdownContent"id="content"/></div>
</template><script>
import VueMarkdown from "vue-markdown";export default {components: {VueMarkdown,},data() {return {markdownContent: "",};},mounted() {this.loadMarkdownFile();},methods: {async loadMarkdownFile() {try {// api.md文件存放在根目录下的public文件夹中const response = await fetch("/api.md");const markdownText = await response.text();this.markdownContent = markdownText;} catch (error) {console.error("Failed to load the Markdown file:", error);}}, },
};
</script>

此时,打开浏览器查看,页面中已经正常渲染markdown文件了。

3、生成目录大纲

现在,我们需要有目录大纲方便我们查看文档。我的思路是,首先拿到markdown文件的html结构,然后找到所有H1-H5的标题标签,并给这些标签设置id,生成一个新数组,通过这个数组生成目录结构,说干就干。

//html部分<div class="api-tree" id="tree"><el-tree:data="tree":default-expand-all="true"@node-click="handleNodeClick"></el-tree>
</div>// js部分
catalogTree() {const content = document.getElementById("content").children;var arr = [];let currentHightestLevel;let parentId;let index = 0;for (let i = 0; i < content.length; i++) {let header = content[i].localName;if (/\b[h][0-9]\b/.test(header)) {let ele = $(content[i]);let name = ele.text();// 设置idele.attr("id", i);let id = i;if (index === 0 || header <= currentHightestLevel) {currentHightestLevel = header;parentId = id;}arr.push({id: id,label: name,parentId: parentId == id ? "0" : parentId,});index++;}}const tree = [];arr.forEach((item) => {if (item.parentId === "0") {tree.push(this.convertArrayToTree(arr, item));}});this.tree = tree;
},
convertArrayToTree(arr, node) {for (let i = 0; i < arr.length; i++) {if (arr[i].parentId === node.id) {const res = this.convertArrayToTree(arr, arr[i]);if (node.children) {node.children.push(res);} else {node.children = [res];}}}return node;
},
handleNodeClick(data) {let anchorElement = document.getElementById(data.id);if (anchorElement) {anchorElement.scrollIntoView({behavior: "smooth",block: "end",});}
},

4、大功告成,最后,附上全部代码,带css样式

<template><div class="page-api" id="myElement"><div class="api-tree" id="tree"><el-tree:data="tree":default-expand-all="true"@node-click="handleNodeClick"></el-tree></div><VueMarkdownclass="api-content":source="markdownContent"id="content"/></div>
</template><script>
import VueMarkdown from "vue-markdown";
import $ from "jquery";export default {components: {VueMarkdown,},data() {return {markdownContent: "",tree: [],};},mounted() {this.loadMarkdownFile();},methods: {async loadMarkdownFile() {try {const response = await fetch("/api.md");const markdownText = await response.text();this.markdownContent = markdownText;this.$nextTick(() => {this.catalogTree();});} catch (error) {console.error("Failed to load the Markdown file:", error);}},catalogTree() {const content = document.getElementById("content").children;var arr = [];let currentHightestLevel;let parentId;let index = 0;for (let i = 0; i < content.length; i++) {let header = content[i].localName;if (/\b[h][0-9]\b/.test(header)) {let ele = $(content[i]);let name = ele.text();// 设置idele.attr("id", i);// let id = ele.children("a").attr("id");let id = i;if (index === 0 || header <= currentHightestLevel) {currentHightestLevel = header;parentId = id;}arr.push({id: id,label: name,parentId: parentId == id ? "0" : parentId,});index++;}}const tree = [];arr.forEach((item) => {if (item.parentId === "0") {tree.push(this.convertArrayToTree(arr, item));}});this.tree = tree;},convertArrayToTree(arr, node) {for (let i = 0; i < arr.length; i++) {if (arr[i].parentId === node.id) {const res = this.convertArrayToTree(arr, arr[i]);if (node.children) {node.children.push(res);} else {node.children = [res];}}}return node;},handleNodeClick(data) {let anchorElement = document.getElementById(data.id);let scrollPosition = anchorElement.offsetTop - 20;let myElement = document.getElementById("myElement");myElement.scrollTo({left: 0,top: scrollPosition,behavior: "smooth",});// if (anchorElement) {//     anchorElement.scrollIntoView({//         behavior: "smooth",//         block: "end",//     });// }},},
};
</script><style lang="scss">
.page-api {display: flex;height: 100%;overflow-y: scroll;.api-tree {position: fixed;left: 20px;top: 120px;width: 200px;height: calc(100% - 160px);overflow-y: scroll;z-index: 99;.el-tree {background: none;color: #fff;.el-tree-node:focus > .el-tree-node__content,.el-tree-node__content:hover {background: none;color: rgb(24, 144, 255);}}}.api-content {flex: 1;margin-left: 220px;padding: 0 30px;color: rgba(255, 255, 255, 0.75);h3 {margin-left: 25px;}code {border-radius: 2px;color: #e96900;margin: 0 2px;padding: 3px 5px;white-space: pre-wrap;}table {border-collapse: collapse;border-spacing: 0;th,td {border: 1px solid #ddd;padding: 6px 13px;margin: 0;}}pre {background: rgba(0, 0, 0, 0.7);padding: 20px 30px;}}
}
</style>

相关文章:

记一次使用vue-markdown在vue中解析markdown格式文件,并自动生成目录大纲

先上效果图 如图所示&#xff0c;在网页中&#xff0c;能直接解析markdown文档&#xff0c;并且生成目录大纲&#xff0c;也支持点击目录标题跳转到对应栏目中&#xff0c;下面就来讲讲是如何实现此功能的。 1、下载vue-markdown yarn add vue-markdown 2、在页面中渲染markdo…...

力扣每日一题35:搜索插入的位置

题目描述&#xff1a; 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target 5…...

Iptabels的相关描述理解防火墙的必读文章

Iptabels是与Linux内核集成的包过滤防火墙系统&#xff0c;几乎所有的linux发行版本都会包含Iptables的功能。如果 Linux 系统连接到因特网或 LAN、服务器或连接 LAN 和因特网的代理服务器&#xff0c; 则Iptables有利于在 Linux 系统上更好地控制 IP 信息包过滤和防火墙配置。…...

Maven 构建项目测试

在上一章节中我们学会了如何使用 Maven 创建 Java 应用。接下来我们要学习如何构建和测试这个项目。 进入 C:/MVN 文件夹下&#xff0c;打开 consumerBanking 文件夹。你将看到有一个 pom.xml 文件&#xff0c;代码如下&#xff1a; <project xmlns"http://maven.apa…...

机器学习 - 似然函数:概念、应用与代码实例

目录 一、概要二、什么是似然函数数学定义似然与概率的区别重要性举例 三、似然函数与概率密度函数似然函数&#xff08;Likelihood Function&#xff09;定义例子 概率密度函数&#xff08;Probability Density Function, PDF&#xff09;定义 区别与联系 四、最大似然估计&am…...

LeetCode 热题 100-49. 字母异位词分组

题目描述 给你一个字符串数组&#xff0c;请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 示例 1: 输入: strs [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”] 输出: [[“bat”],[“n…...

TensorFlow入门(十九、softmax算法处理分类问题)

softmax是什么? Sigmoid、Tanh、ReLU等激活函数,输出值只有两种(0、1,或-1、1或0、x),而实际现实生活中往往需要对某一问题进行多种分类。例如之前识别图片中模糊手写数字的例子,这个时候就需要使用softmax算法。 softmax的算法逻辑 如果判断输入属于某一个类的概率大于属于其…...

刷题用到的非常有用的函数c++(持续更新)

阅读导航 字符串处理类一、stoi()&#xff08;将字符串转换为整数类型&#xff09;二、to_string()&#xff08;将整数类型转换为字符串类型&#xff09;三、stringstream函数&#xff08;将一个字符串按照指定的分隔符进行分词&#xff09; 字符串处理类 一、stoi()&#xff…...

黑客技术(网络安全)——自学思路

如果你想自学网络安全&#xff0c;首先你必须了解什么是网络安全&#xff01;&#xff0c;什么是黑客&#xff01;&#xff01; 1.无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防两面性&#xff0c;例如 Web 安全技术&#xff0c;既有 Web 渗透2.也有 Web 防…...

lNmp安装:

一、LNMP LNMP架构是目前成熟的企业网站应用模式之一&#xff0c;指的是协同工作的一整套系统和相关软件&#xff0c; 能够提供动态Web站点服务及其应用开发环境。LNMP是一个缩写词&#xff0c;具体包括Linux操作系统、nginx网站服务器、MySQL数据库服务器、 PHP&#xff08;或…...

Fisher辨别分析

问题要求 在UCI数据集上的Iris和Sonar数据上验证算法的有效性。训练和测试样本有三种方式&#xff08;三选一&#xff09;进行划分&#xff1a; &#xff08;一&#xff09; 将数据随机分训练和测试&#xff0c;多次平均求结果 &#xff08;二&#xff09;K折交叉验证 &…...

【Zookeeper专题】Zookeeper选举Leader源码解析

目录 前言阅读建议课程内容一、ZK Leader选举流程回顾二、源码流程图三、Leader选举模型图 学习总结 前言 为什么要看源码&#xff1f;说实在博主之前看Spring源码之前没想过这个问题。因为我在看之前就曾听闻大佬们说过【JavaCoder三板斧&#xff1a;Java&#xff0c;Mysql&a…...

机器学习之自训练协同训练

前言 监督学习往往需要大量的标注数据&#xff0c; 而标注数据的成本比较高 &#xff0e; 因此 &#xff0c; 利用大量的无标注数据来提高监督学习的效果有着十分重要的意义&#xff0e; 这种利用少量标注数据和大量无标注数据进行学习的方式称为 半监督学习 &#xff08; Semi…...

ubuntu 通过apt-get快速安装 docker

在使用 apt-get 安装 Docker 之前,你需要确保你的系统已经准备好并且已经更新了软件包列表。以下是在 Ubuntu 系统上使用 apt-get 安装 Docker 的步骤: 更新软件包列表: sudo apt-get update 安装依赖软件包,以确保可以通过 HTTPS 使用存储库: sudo apt-get install apt-t…...

C++医院影像科PACS源码:三维重建、检查预约、胶片打印、图像处理、测量分析等

PACS连接DICOM接口的医疗器械&#xff08;如CT、MRI、CR、DR、DSA、各种窥镜成像系统设备等&#xff09;&#xff0c;实现图像无损传输&#xff0c;实现DICOM胶片打印机回传打印功能&#xff0c;支持各种图像处理&#xff0c;可以进行窗技术调节&#xff0c;与登记台管理系统共…...

企业聊天应用程序使用 Kubernetes

1. 客户端-服务器工作流程 客户端&#xff1a;在我们的架构中&#xff0c;客户端可以分为三种类型&#xff1a;iOS 和 Android 移动应用程序以及 Web 聊天。移动应用程序首先通过 API 网关服务与服务器进行通信&#xff0c;其中客户端会生成一个访问令牌&#xff0c;该令牌将授…...

记录用命令行将项目打包成war包

记录用命令行将项目打包成war包 找到项目的pom.xml 在当前路径下进入cmd 输入命令 mvn clean package 发现报错了 Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.2:war (default-war) on project MMS: Error assembling WAR: webxml attribute is req…...

Linux基础知识笔记

Linux基础知识笔记 介绍/dev/null作用2>&1作用 介绍 记录linux基础知识&#xff0c;持续更新中… /dev/null作用 /dev/null 是一个特殊的设备文件&#xff0c;可以将数据重定向到这个文件中&#xff0c;从而实现将输出或错误信息丢弃的效果。在 Linux 系统中&#xf…...

Laya3.0 入门教程

点击play箭头 点击右边的开发者工具 就会弹出 chrome的调试窗口 然后定位到你自己的ts文件 直接在ts里断点即可 不需要js文件 如何自动生成代码&#xff1f; 比如你打开一个新项目 里面显示的是当前场景 只需要点击 UI运行时 右边的框就可以了 他会自动弹窗提示你 创建一个文…...

3D全景虚拟样板间展销系统扩展用户市场范围

VR样板间&#xff0c;能够真实还原现场&#xff0c;定制需要的场景。让一切比真实更真实。用户可以720度看房&#xff0c;自由行走在空间里&#xff0c;直观感受各空间的大小&#xff0c;看到自己家中的“未来样子”&#xff0c;同时通过操控手柄&#xff0c;控制整个智能家居系…...

如何编写lua扩展库

很多人都听过lua,也见过lua脚本,但可能不理解为什么lua脚本里面会有这么多没见过的函数, 而且这些函数功能是如此强大,能上天入地,无所不能 其实这些函数并不是lua自带的,都是由程序作者造出来的隐藏在了他们的主程序里 一般运行lua脚本,我们会使用自带的解释器,当你拿到一份…...

Java List 中存不同的数据类型

在最近的实践中&#xff0c;有人突然问了一个问题&#xff1a; 在 Java 的 List 中可以存不同的数据类型吗&#xff1f; 这个问题突然给问到了&#xff0c;我们都知道 Java 中的 List 中存的是对象&#xff0c;通常我们定义都会这样的定义&#xff1a; List<String> t…...

pyqt5:openpyxl 读取 Excel文件,显示在 QTableWidget 中

pip install openpyxl openpyxl-3.1.2-py2.py3-none-any.whl (249 kB) et_xmlfile-1.1.0-py3-none-any.whl (4.7 kB) 摘要&#xff1a;A Python library to read/write Excel 2010 xlsx/xlsm files pip install pyqt5; pip install pyqt5-tools; 编写 openpyxl_pyqt5.py 如…...

在RabbitMQ中使用新的MQTT 5.0功能

MQTT是物联网&#xff08;IoT&#xff09;的标准协议&#xff0c;是轻量级的&#xff0c;协议头很小&#xff0c;可以节省网络带宽。MQTT也很有效&#xff0c;与其他消息传递协议相比&#xff0c;客户端通过更短的握手进行连接和身份验证。 以下是本文介绍的MQTT 5.0功能列表&…...

flinkcdc 体验

0 flink版本 踩雷 java代码操作 flink Table/SQL API 和 DataStream API 编写程序后&#xff0c;打成jar包丢到flink集群运行&#xff0c;报错首选需要考虑flink集群版本和 jar包中maven依赖的版本是否一致。 目前网上flink、flinkcdc相关博文绝大部分是基于flink1.13、1.14编…...

Kafka知识补充

如何避免 Rebalance 最简单粗暴的就是 &#xff1a; 减少组成员数量发生变化 每个 Consumer 实例都会定期地向 Coordinator 发送心跳请求&#xff0c;表明它还存活着。如果某个 Consumer 实例不能及时地发送这些心跳请求&#xff0c;Coordinator 就会认为该 Consumer 已经“死…...

【MAC】升级 Mac os 后报错

背景 17 年买的 mac&#xff0c;发现很多软件都无法安装&#xff0c;于是升级 mac os 到 10.13&#xff0c;从官网下载 10.13 版本&#xff0c;之后升级&#xff0c;升级还算顺利。但使用 git 的时候发现出现问题了。 问题 使用 git 出现如下错误 xcrun: error: invalid ac…...

LeetCode(力扣)416. 分割等和子集Python

LeetCode416. 分割等和子集 题目链接代码 题目链接 https://leetcode.cn/problems/partition-equal-subset-sum/ 代码 class Solution:def canPartition(self, nums: List[int]) -> bool:sum 0dp [0]*10001for num in nums:sum numif sum % 2 1:return Falsetarget …...

Redis之缓存一致性

Redis之缓存一致性 1 缓存更新策略1.1 内存淘汰1.2 过期删除1.3 主动更新1.4 三种缓存更新策略的对比 2 更新缓存的两种方式3 缓存更新策略的实现方式3.1 先更新DB&#xff0c;后更新缓存3.2 先更新DB&#xff0c;后删除缓存3.3 先更新缓存&#xff0c;后更新DB3.4 先删除缓存&…...

LeetCode-199-二叉树的右视图

题目描述&#xff1a; 题目链接&#xff1a;LeetCode-199-二叉树的右视图 解题思路&#xff1a; 在 102 的基础之上进行改进&#xff0c;一维数组每次只保存 size1 时候的值 代码实现&#xff1a; class Solution {public List<Integer> rightSideView(TreeNode root) {i…...