使用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

运行结果

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

相关推荐
寻星探路3 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
曹牧6 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
爬山算法6 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty7257 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai