使用marked将markdown渲染成HTML的基本操作

文章目录


前言

最近想写一个博客网站,于是就想看看markdown 是如何转化成html的,本来我使用的是mvion-editor来编写我的markdown,但在实现只查看我上传的markdown是感觉有点笨重,于是就找到了marked 整个工具

安装

bash 复制代码
npm install marked

可以使用的其他工具

引入实例

默认情况下,Marked 将选项和扩展存储在全局范围内。这意味着更改一个脚本中的选项也会更改另一个脚本中的选项,因为它们共享同一个实例。

比如这种

javascript 复制代码
import {marked} from 'marked'
marked.renderer()

如果你不想改变全局范围,你可以创建一个新的 Marked 实例,以确保选项和扩展是本地范围的

javascript 复制代码
import { Marked } from 'marked';
const marked = new Marked([options, extension, ...]);

parse() 功能

javascript 复制代码
import { marked } from 'marked';
marked.parse(markdownString [,options])``

options 选项

还有一种使用option的方法

javascript 复制代码
// Create reference instance
import { marked } from 'marked';

// Set options
marked.use({
  async: true,
  pedantic: false,
  gfm: true,
});

// Compile
console.log(marked.parse(markdownString));

render 渲染器

渲染器定义给定标记的 HTML 输出。如果你在传递给 marked.use() 的选项对象中提供 renderer,则对象中的任何函数都将覆盖该标记类型的默认处理。

this.parser

将原始标记转换为 HTML

处理内联元素的嵌套结构

只能在渲染器的普通函数方法中访问(箭头函数不可用)

是 marked 内部 API 的一部分,用于构建完整的渲染链

块级渲染器方法

space(token: Tokens.Space): string

code(token: Tokens.Code): string

blockquote(token: Tokens.Blockquote): string

html(token: Tokens.HTML | Tokens.Tag): string

heading(token: Tokens.Heading): string

hr(token: Tokens.Hr): string

list(token: Tokens.List): string

listitem(token: Tokens.ListItem): string

checkbox(token: Tokens.Checkbox): string

paragraph(token: Tokens.Paragraph): string

table(token: Tokens.Table): string

tablerow(token: Tokens.TableRow): string

tablecell(token: Tokens.TableCell): string

内联级别渲染器方法

strong(token: Tokens.Strong): string

em(token: Tokens.Em): string

codespan(token: Tokens.Codespan): string

br(token: Tokens.Br): string

del(token: Tokens.Del): string

link(token: Tokens.Link): string

image(token: Tokens.Image): string

text(token: Tokens.Text | Tokens.Escape | Tokens.Tag): string

使用示例

javascript 复制代码
// Create reference instance
import { marked } from 'marked';

// Override function
const renderer = {
  heading({ tokens, depth }) {
    const text = this.parser.parseInline(tokens);
    const escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');

    return `
            <h${depth}>
              <a name="${escapedText}" class="anchor" href="#${escapedText}">
                <span class="header-link"></span>
              </a>
              ${text}
            </h${depth}>`;
  }
};

marked.use({ renderer });
// Run marked
console.log(marked.parse('# heading+'));

上面的方法会创建一个新的renderer所有的渲染器只剩下你定义的heading 下面的是进行override

javascript 复制代码
import { marked } from 'marked';

// 获取默认渲染器
const renderer = new marked.Renderer();

// 覆盖默认渲染器的 heading 方法
renderer.heading = function({ tokens, depth }) {
  const text = this.parser.parseInline(tokens);
  const escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');

  return `
          <h${depth}>
            <a name="${escapedText}" class="anchor" href="#${escapedText}">
              <span class="header-link"></span>
            </a>
            ${text}
          </h${depth}>`;
};

marked.setOptions({
  renderer: renderer
})

运行实例

在下面我重写了img 的渲染器,我感觉太大了,可以根据自己需要的大小,来进行替换,我的代码是根据,自己的项目来写的,想要运行的可以替换,下面的content.value的值,或者私信,我把markdown的部分,发出来,这里就不粘贴了

javascript 复制代码
<template>
  <div class="makedownMain" style="width:100vw;height:100vh">
    <div class="main">
    <div class="side"></div>
    <div class="main1">
  <el-scrollbar>
  <div class="title"><h1>{{ driftName }}</h1></div>
  <div class="content">
  <div v-html="htmlContent"></div>
  </div>
  </el-scrollbar>
  </div>
  </div>
  </div>
</template>

<script setup>
import { ref, onMounted} from 'vue'
import { marked } from 'marked'
import { userheaders } from '../../store/urlStore'
import { storeToRefs } from 'pinia'

const headers = userheaders()
const { content ,driftName} = storeToRefs(headers)
const htmlContent = ref('')



const renderer = new marked.Renderer()
renderer.image = function({ href, title, text }) {
  // href是图片URL,text是alt文本
  const altText = text || '图片'
  const escapedText = altText.toLowerCase().replace(/[^\w]+/g, '-')
  
  return `
    <img src="${href}" 
         alt="${escapedText}" 
         class="custom-markdown-image"
          ">
  `
}

marked.setOptions({
  renderer: renderer
})

onMounted(() => {
  if (content.value) {
    // 将markdown转换为HTML
    htmlContent.value = marked.parse(content.value)
    
  }})
</script>

<style>
  .title{
    margin-bottom: 5vh;
    
  }
.makedownMain{
  display:flex;
  
  overflow-y: auto;
  justify-content: center;
}
.main{
width:80vw;
box-shadow: var(--el-border-color-light) 0px 0px 10px;
display: flex;

}
.main1{
  width:65vw;
  height:100vh;
  background-color: aliceblue;
  box-shadow: var(--el-border-color-light) 0px 0px 10px;
  
}
img.custom-markdown-image {
  max-width: 50vw !important;
  height: auto !important;
  object-fit: contain !important;
  display: block !important;
  margin: 10px 0 !important;
  border-radius: 4px !important;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important;
}

.side{
  width:15vw;
  height:100vh;
  background-color:aliceblue;
}
.content{
  display: flex;
  height: inherit;
  width: inherit;
  justify-content: center;
}

</style

运行结果

可以看到我已经成功渲染出来了

相关推荐
Hilaku2 小时前
当 Gemini 3 能写出完美 CSS 时,前端工程师剩下的核心竞争力是什么?
前端·javascript·ai编程
Hello.Reader2 小时前
Flink ML 线性 SVM(Linear SVC)入门输入输出列、训练参数与 Java 示例解读
java·支持向量机·flink
oioihoii2 小时前
C++数据竞争与无锁编程
java·开发语言·c++
最贪吃的虎2 小时前
什么是开源?小白如何快速学会开源协作流程并参与项目
java·前端·后端·开源
资生算法程序员_畅想家_剑魔2 小时前
Java常见技术分享-16-多线程安全-并发编程的核心问题
java·开发语言
We....2 小时前
Java SPI 机制
java·开发语言
裴嘉靖2 小时前
Vue + ECharts 实现图表导出为图片功能详解
前端·vue.js·echarts
用泥种荷花2 小时前
【LangChain学习笔记】输出解析器
前端
海南java第二人2 小时前
Java无锁并发编程:volatile+CAS原子类深度解析
java·cas·volatile