目录
本文收录在《如何开发一个自己的笔记软件》系列中,该系列源码均可在 Blossom 笔记软件 仓库中查看。仓库地址:
安装
源码地址 Markedjs 源码地址
官方文档 Markedjs 官方文档
安装依赖
npm install marked
npm install @types/marked
npm install marked-highlight
npm install highlight.js
使用
你可以直接引入marked,默认是全局共享同一个实例
// 引入默认实例
import { marked } from 'marked'
marked.use({
// 开启异步渲染
async: true,
pedantic: false,
gfm: true,
mangle: false,
headerIds: false
})
// 异步方式渲染
marked.parse(markdown, { async: true }).then((html: string) => {
console.log(html)
})
// 同步方式渲染
const html = marked.parse(markdown)
如果你要创建一个新实例,可以使用如下方式
import { Marked } from 'marked'
const newMarked = new Marked({ mangle: false, headerIds: false })
添加代码高亮
你需要安装下列两个依赖
npm install marked-highlight
npm install highlight.js
然后进行如下配置,代码块中的内容会自动添加高亮样式。
import { marked } from 'marked'
import { markedHighlight } from "marked-highlight"
import hljs from 'highlight.js'
// 注意引入样式,你可以前往 node_module 下查看更多的样式主题
import 'highlight.js/styles/base16/darcula.css'
// 高亮拓展
marked.use(markedHighlight({
langPrefix: 'hljs language-',
highlight(code, lang) {
const language = hljs.getLanguage(lang) ? lang : 'shell'
return hljs.highlight(code, { language }).value
}
}))
自定义渲染格式
你可以重写 renderer 函数来自定义渲染结果。下方会介绍一些笔者开发的笔记软件中用到的拓展方式。
源码地址:Markedjs 封装
拓展标题ID实现目录跳转
重写 heading 函数,并为所有的标题标签添加ID来实现目录跳转。
let html:string = ''
const renderer = {
/**
* 标题解析为 TOC 集合, 增加锚点跳转
*
* @param text 标题内容
* @param level 标题级别
*/
heading(text: any, level: number): string {
const realLevel = level
return `<h${realLevel} id="${realLevel}-${text}">${text}</h${realLevel}>`
}
}
// 重写标题的渲染结果
marked.use({ renderer: renderer })
marked.parse('# 标题1', { async: true }).then((htmlResult: string) => {
// 结果为 <h1 id="1-标题1">标题1</h1>
html = htmlResult
})
然后解析 html 来自动获取标题标签(h1 ~ h6),并解析成一个数组。
// 定义目录结构
export interface Toc {
name: string,
id: string,
level: number
}
export const initTocs = (id: string): Toc[] => {
// 获取指定ID,渲染后的html都在该标签内
let ele = document.getElementById(id)
if (ele == null || undefined) {
return []
}
let heads = document.getElementById(id)!.querySelectorAll('h1, h2, h3, h4, h5, h6');
let tocs: Toc[] = []
for (let i = 0; i < heads.length; i++) {
let head = heads[i]
let level = 1;
let name = (head as HTMLElement).innerText
let id = head.id
switch (head.localName) {
case 'h2':
level = 2;
break;
case 'h3':
level = 3;
break;
case 'h4':
level = 4;
break;
}
let toc: Toc = {
name: name,
id: id,
level: level
}
tocs.push(toc)
}
return tocs
}
随后无论你使用 vue 还是 react,你都可以将数组结果列渲染到你的页面上。并为每一个元素添加一个 click 事件,即可以实现跳转。比方说 vue 中:
<template>
<div :class="['toc', 'toc-' + toc.level]" v-for="toc in tocs" :key="toc.id" @click="toScroll(toc.id)">
{{ toc.name }}
</div>
</template>
<script setup lang="ts">
const toScroll = (id: string) => {
let ele: HTMLElement = document.getElementById(id) as HTMLElement
if (ele == null || ele == undefined) {
return
}
(ele.parentNode as Element).scrollTop = ele.offsetTop
}
</script>
拓展图片的样式
可以通过约定 markdown 格式,来实现更加丰富的样式。比如下方的例子中,为图片增加了宽度和阴影的拓展。只需要在图片名称中指定相关配置

// 拓展语法标识
const grammar = '##'
const renderer = {
/**
* 拓展图片
*
* @param href 图片路径
* @param _title null
* @param text 图片的名称
*/
image(href: string | null, _title: string | null, text: string): string {
let width = 'auto' // 宽度
let style = '' // 样式
let tags: string[] = text.split(grammar)
if (tags.length > 1) {
for (let i = 0; i < tags.length; i++) {
let tag = tags[i]
if (tag === 'shadow') {
style += 'box-shadow: 0 0 3px #000000;'
}
//
if (tag.startsWith('w')) {
width = tags[i].substring(1)
if (!width.endsWith('%')) {
width += 'px'
}
}
}
}
return `<img width="${width}" style="${style}" src="${href}" alt="${text}">`
}
}
// 重写图片的渲染结果
marked.use({ renderer: renderer })
marked.parse('', { async: true }).then((htmlResult: string) => {
// 结果为 <img width="200px" style="box-shadow: 0 0 3px #000000;" src="http://domain.com" alt="图片名称##w200##shadow">图片名称</img>
html = htmlResult
})
更多拓展
除此之外,笔者还拓展了一些其他的 markedjs 渲染方法。这些拓展内容都可以在Markedjs 封装中查看。
1. 使用表格进行布局
2. 多色引用块
3. 视频引用
4. katex 语法拓展
5. mermaid 图表拓展
%%{init: { 'theme': 'neutral' } }%%
timeline
title Blossom 版本发布时间线
2023-06-10 : 写下了第一行代码
2023-08-10 : 发布了 1.0 版本
2023-08-15 : 发布了 1.1 版本
: 支持了 katex 和 mermaid
2023-09-01 : 发布了 1.2 版本
: 一个完整的笔记软件 基本成型