markdown 转 html 需要先安装三个包:browser-sync,ejs,marked
第一步,先准备一个 ejs 模板:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><%= title %></title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<%- content %>
</body>
</html>
第二步,准备生成 html 的样式文件:
/* Markdown通用样式 */
/* 设置全局字体样式 */
body {
font-family: Arial, sans-serif;
font-size: 16px;
line-height: 1.6;
color: #333;
}
/* 设置标题样式 */
h1,
h2,
h3,
h4,
h5,
h6 {
margin-top: 1.3em;
margin-bottom: 0.6em;
font-weight: bold;
}
h1 {
font-size: 2.2em;
}
h2 {
font-size: 1.8em;
}
h3 {
font-size: 1.6em;
}
h4 {
font-size: 1.4em;
}
h5 {
font-size: 1.2em;
}
h6 {
font-size: 1em;
}
/* 设置段落样式 */
p {
margin-bottom: 1.3em;
}
/* 设置链接样式 */
a {
color: #337ab7;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* 设置列表样式 */
ul,
ol {
margin-top: 0;
margin-bottom: 1.3em;
padding-left: 2em;
}
/* 设置代码块样式 */
pre {
background-color: #f7f7f7;
padding: 1em;
border-radius: 4px;
overflow: auto;
}
code {
font-family: Consolas, Monaco, Courier, monospace;
font-size: 0.9em;
background-color: #f7f7f7;
padding: 0.2em 0.4em;
border-radius: 4px;
}
/* 设置引用样式 */
blockquote {
margin: 0;
padding-left: 1em;
border-left: 4px solid #ddd;
color: #777;
}
/* 设置表格样式 */
table {
border-collapse: collapse;
width: 100%;
margin-bottom: 1.3em;
}
table th,
table td {
padding: 0.5em;
border: 1px solid #ccc;
}
/* 添加一些额外的样式,如图片居中显示 */
img {
display: block;
margin: 0 auto;
max-width: 100%;
height: auto;
}
/* 设置代码行号样式 */
pre code .line-numbers {
display: inline-block;
width: 2em;
padding-right: 1em;
color: #999;
text-align: right;
user-select: none;
pointer-events: none;
border-right: 1px solid #ddd;
margin-right: 0.5em;
}
/* 设置代码行样式 */
pre code .line {
display: block;
padding-left: 1.5em;
}
/* 设置代码高亮样式 */
pre code .line.highlighted {
background-color: #f7f7f7;
}
/* 添加一些响应式样式,适应移动设备 */
@media only screen and (max-width: 768px) {
body {
font-size: 14px;
line-height: 1.5;
}
h1 {
font-size: 1.8em;
}
h2 {
font-size: 1.5em;
}
h3 {
font-size: 1.3em;
}
h4 {
font-size: 1.1em;
}
h5 {
font-size: 1em;
}
h6 {
font-size: 0.9em;
}
table {
font-size: 14px;
}
}
第三步,准备一个 md 文件:
EventEmitter 像是 Vue2 的event bus,或者Vue3 的 mitt。主要采用了发布订阅模式来处理事件。
```js
const EventEmitter = require('events');
const event = new EventEmitter()
// 监听(订阅)事件
event.on('test',(data)=>{
console.log(data)
})
event.emit('test','testtt') // 派发事件
监听的数量默认为10 个。当然我们可以自行修改event.setMaxListeners(20)
。
once 方法只监听一次。off 方法停止监听。
可以发现 process 可支持这些方法,底层就是因调用了 EventEmitter 的原型对象给 process 对象。主要使用 Object.setPrototypeOf(target, source)
。
const EventEmitter = require('events')
ObjectSetPrototypeOf(ObjectGetPrototypeOf(process), EventEmitter.prototype)
第四步,转:
const ejs = require('ejs')
const fs = require('fs')
const marked = require('marked')
const browserSync = require('browser-sync')
let browser;
// 起一个服务 支持热更新
const server = () => {
browser = browserSync.create()
browser.init({
server: {
baseDir: './',
index: 'index.html'
}
})
}
const init = (callback) => {
// 读取 md 的内容
const md = fs.readFileSync('README.md', 'utf8')
// 读取文件并填充内容
ejs.renderFile('template.ejs', {
content: marked.parse(md),
title: "markdown to html"
}, (err, data) => {
if (err) throw err
fs.writeFileSync('index.html', data)
callback && callback()
})
}
//监听文件变化
fs.watchFile('README.md', (curr, prev) => {
if (curr.mtime !== prev.mtime) {
init(() => {
browser.reload()
})
}
})
init(() => {
server()
})
browser-sync 的主要作用是使支持热更新,实时预览,自动刷新
marked 主要用于 md 转 html
ejs JavaScript 的模板引擎,支持在 html 动态嵌入内容
此外,当我们同时多端打开该 html 文件时,多端都会同步运行(同步预览滑动拖拽)。