node+express服务给前端提供markdown数据,前端渲染md文件在页面上

发布时间 2023-11-13 14:45:49作者: william_new
本文介绍后端怎么把markdown文件发给前端,前端又怎么渲染在页面中。

先看效果图

md文件代码

 

前端网页渲染: 

先介绍node+express怎么提供接口:

const express = require("express");
const router = express.Router();
const fs = require("fs");

router.get("/api/getMarkDownContent", (req, res, next) => {
  //这里可以通过 query 拿到get请求的参数,可以实现根据参数返回不同的md文件等效果
  const { query } = req; 
  
  //拿到md文件的全路径
  let filePath = process.cwd() + "/routes/test.md";

  //利用node自带的fs模块------> 创建可读流
  let fileStream = fs.createReadStream(filePath);

  //想要读取到可读流的数据,需要监听data事件
  fileStream.on("data", function (data) {
    // res.write(data, "binary");  //直接返回
    //封装返回
    res.send({
      code: 200,
      data: data.toString(), //Buffer转换为字符串
      msg: '请求成功'
    })
  });

  //错误处理
  fileStream.on("error", (err) => {
    next(err);
  });

  //文件读取完毕
  fileStream.on("end", function () {
    res.end();
  });
});

module.exports = router;
View Code

再介绍前端axios获取数据以及渲染:

<template>
    <div class="markdown-preview">
      <div v-html="renderedMarkdown"></div>
    </div>
</template>

<script setup>
import hljs from 'highlight.js'; //需要 npm install highlight.js
import 'highlight.js/styles/atom-one-dark.css'; // 选择一个自己喜欢的样式风格
import MarkdownIt from 'markdown-it'; //需要 npm install markdown-it
import { getMdContentApi } from '@/xxx' //这里写你自己项目的http请求路径
import { ref, onMounted } from 'vue'

let renderedMarkdown = ref('')

onMounted(async () => {
  const md = new MarkdownIt({
    html: true, // 允许在 Markdown 中使用 HTML
    linkify: true, // 自动转换链接为可点击的链接形式
    typographer: true, // 启用智能引号等文本转换功能
    highlight: function (str, lang) {
      if (lang && hljs.getLanguage(lang)) {
        try {
          return `<pre class="hljs"><code>${hljs.highlight(lang, str, true).value}</code></pre>`;
        } catch (error) {
          console.log(error)
        }
      }
      return `<pre class="hljs"><code>${md.utils.escapeHtml(str)}</code></pre>`;
    },
  });
  const response = await getMdContentApi()
  renderedMarkdown.value = md.render(response.data);

})
</script>
  1. 上面的例子用的是vue3。vue2或其它框架用法类似。
  2. 到这一步,页面已经把后端返回的markdown文件数据渲染成了html了。
  3. 部分样式需要自己去写才能达到满意的效果,我给我上面效果图中,自己加的一个样式代码:
// highlight.js
.markdown-preview ul{
    list-style-type: disc;
}
.markdown-preview ol{
    list-style-type: decimal; 
}
.markdown-preview .hljs{
    font-size: 14px;
    padding: 14px 24px;
    overflow: auto;
    border-radius: 8px;
}
.markdown-preview li code,.markdown-preview p code{
    background-color: #f0f0f0;
    border-radius: 3px;
}

.markdown-preview code{
    line-height: 1.5;
    font-family: Menlo,Monaco,Consolas,'Courier New',monospace;
}

.markdown-preview h1,.markdown-preview h2,.markdown-preview h3,.markdown-preview h4,.markdown-preview h5,.markdown-preview h6 {
    line-height: 1.2;
    margin-top: 1em;
    margin-bottom: 16px;
    color: #000
}

.markdown-preview h1 {
    font-size: 2.25em;
    font-weight: 300;
    padding-bottom: .3em
}

.markdown-preview h2 {
    font-size: 1.75em;
    font-weight: 400;
    padding-bottom: .3em
}

.markdown-preview h3 {
    font-size: 1.5em;
    font-weight: 500
}

.markdown-preview h4 {
    font-size: 1.25em;
    font-weight: 600
}

.markdown-preview h5 {
    font-size: 1.1em;
    font-weight: 600
}

.markdown-preview h6 {
    font-size: 1em;
    font-weight: 600
}

.markdown-preview h1,.markdown-preview h2,.markdown-preview h3,.markdown-preview h4,.markdown-preview h5 {
    font-weight: 600
}

.markdown-preview h5 {
    font-size: 1em
}

.markdown-preview h6 {
    color: #5c5c5c
}

.markdown-preview strong {
    color: #000
}

.markdown-preview del {
    color: #5c5c5c
}

.markdown-preview a:not([href]) {
    color: inherit;
    text-decoration: none
}

.markdown-preview a {
    color: #08c;
    text-decoration: none
}

.markdown-preview a:hover {
    color: #00a3f5;
    text-decoration: none
}

.markdown-preview img {
    max-width: 100%
}

.markdown-preview>p {
    margin-top: 0;
    margin-bottom: 16px;
    word-wrap: break-word
}

.markdown-preview>ol,.markdown-preview>ul {
    margin-bottom: 16px
}

.markdown-preview ol,.markdown-preview ul {
    padding-left: 2em
}

.markdown-preview ol.no-list,.markdown-preview ul.no-list {
    padding: 0;
    list-style-type: none
}

.markdown-preview ol ol,.markdown-preview ol ul,.markdown-preview ul ol,.markdown-preview ul ul {
    margin-top: 0;
    margin-bottom: 0
}

.markdown-preview li {
    margin-bottom: 0
}

.markdown-preview li.task-list-item {
    list-style: none
}

.markdown-preview li>p {
    margin-top: 0;
    margin-bottom: 0
}

.markdown-preview .task-list-item-checkbox {
    margin: 0 .2em .25em -1.8em;
    vertical-align: middle
}

.markdown-preview .task-list-item-checkbox:hover {
    cursor: pointer
}

.markdown-preview blockquote {
    margin: 16px 0;
    font-size: inherit;
    padding: 0 15px;
    color: #5c5c5c;
    background-color: #f0f0f0;
    border-left: 4px solid #d6d6d6
}

.markdown-preview blockquote>:first-child {
    margin-top: 0
}

.markdown-preview blockquote>:last-child {
    margin-bottom: 0
}

.markdown-preview hr {
    height: 4px;
    margin: 32px 0;
    background-color: #d6d6d6;
    border: 0 none
}

.markdown-preview table {
    margin: 10px 0 15px 0;
    border-collapse: collapse;
    border-spacing: 0;
    display: block;
    width: 100%;
    overflow: auto;
    word-break: normal;
    word-break: keep-all
}

.markdown-preview table th {
    font-weight: 700;
    color: #000
}

.markdown-preview table td,.markdown-preview table th {
    border: 1px solid #d6d6d6;
    padding: 6px 13px
}

.markdown-preview dl {
    padding: 0
}

.markdown-preview dl dt {
    padding: 0;
    margin-top: 16px;
    font-size: 1em;
    font-style: italic;
    font-weight: 700
}

.markdown-preview dl dd {
    padding: 0 16px;
    margin-bottom: 16px
}

.markdown-preview blockquote,.markdown-preview dl,.markdown-preview ol,.markdown-preview p,.markdown-preview pre,.markdown-preview ul {
    margin-top: 0;
    margin-bottom: 16px
}

.markdown-preview kbd {
    color: #000;
    border: 1px solid #d6d6d6;
    border-bottom: 2px solid #c7c7c7;
    padding: 2px 4px;
    background-color: #f0f0f0;
    border-radius: 3px
}
View Code

 

ok,大功告成 。