Bootstrap

Vue实现Markdown文件内容显示及代码块高亮

用到的插件有: marked、 highlight.js、 github-markdown-css
安装命令

// 安装 marked
npm install marked
 
// 安装 highlight.js
npm install highlight.js
 
// 安装 github-markdown-css > 复制 GitHub Markdown 样式
npm install github-markdown-css

开始使用(不要忘记在标签内的 class 写入 markdown-body)

<article class="markdown-body" v-html="result"></article>

如果想要给代码块加上行号,可以参考官网:https://highlightjs.org/
API
安装highlight.js

npm install highlight.js

使用

<template>
    <div v-html="result"></div>
</template>
<script setup>
    import { ref } from 'vue'
    import hljs from 'highlight.js'
    // 官网提供多种高亮代码主题(https://highlightjs.org/static/demo/)
    import 'highlight.js/styles/github.css'
    
    const result = ref('');
    
    /**
     * @param {String} content 代码内容
     * @param {String} lang 代码语言
     * @returns table标签及内容
     */
    const lineNumbers = (content, lang) => {
        // 验证当前语言是否存在
        const language = hljs.getLanguage(lang) ? lang : 'plaintext';
        // 使代码转换成带有标签的节点
        const textHtml = hljs.highlight(content, { language }).value;
        
        // 如果不想添加行号可以直接
        // return textHtml;
 
        // 返回分割后的数组
        const lines = getLines(textHtml);
    
        // 自定义代码块的标签节点
        let html = '';
        for (var i = 0, l = lines.length; i < l; i++) {
            let text = lines[i].length > 0 ? lines[i] : ' '
            html += `<tr>
                <td class="blob-num" data-line-number="${i}"></td>
                <td class="blob-code blob-code-inner">${text}</td>
              </tr>`;
        }
    
        return `<table class="highlight">${html}</table>`;
    }
    
    // 根据换行符或回车分割成字符串数组
    const getLines = (text) => {
        if (text.length === 0) return [];
        return text.split(/\r\n|\r|\n/g);
    }
    
    // 要显示的代码内容
    const content = `import hljs from 'highlight.js'
    const lang = hljs.getLanguage('js') ? 'js' : 'plaintext';
    hljs.highlight(str, { lang }).value;`;
    
    result.value = lineNumbers(content, 'js')
</script>

根据自定义代码块的标签类添加自己想要的样式

<style lang="scss">
    table.highlight {
      border-spacing: 0;
      border-collapse: collapse;
      font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas,
        Liberation Mono, monospace;
    }
    
    .blob-num {
      position: relative;
      width: 1%;
      min-width: 50px;
      padding-right: 10px;
      padding-left: 10px;
      font-size: 12px;
      line-height: 20px;
      color: #6e7781;
      text-align: right;
      white-space: nowrap;
      vertical-align: top;
      -webkit-user-select: none;
      user-select: none;
    }
    
    .blob-num::before {
      content: attr(data-line-number);
    }
    
    .blob-code-inner {
      display: table-cell;
      overflow: visible;
      font-size: 12px;
      color: #24292f;
      word-wrap: anywhere;
      white-space: pre;
    }
    
    .blob-code {
      position: relative;
      padding-right: 10px;
      padding-left: 10px;
      line-height: 20px;
      vertical-align: top;
    }
</style>

同时 marked文档也提供了一些选项

import { marked } from 'marked'
import hljs from 'highlight.js' // 代码块高亮
import 'highlight.js/styles/github.css' // 代码块高亮样式
import 'github-markdown-css' // 整体 markdown 样式
 
const result = ref('');
 
// 要显示的 Markdown 文件内容
const content = `# Vue实现Markdown文件内容显示
> 用到的插件有:marked、highlight.js、github-markdown-css
|   插件    |      备注     |
| --------- | ------------- |
| marked    | markdown 显示 |
| highlight | 代码高亮      |`;
 
result.value = marked.parse(content, {
    highlight: function (code, lang) {
      const language = hljs.getLanguage(lang) ? lang : 'plaintext';
      return hljs.highlight(code, { language }).value;
    }
});
;