整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Node.js 学习笔记:构建 Web 服务

例3. 构建 Web 服务器

这部分示例将致力于用 Node.js 模拟一个类似于 Apache 的 Web 服务器,处理浏览器端的请求,将相关的页面响应给浏览器。首先,我们要在code目录下执行mkdir 03_webSever命令来创建用于存放这一组示例的目录。然后执行以下步骤:

  1. 在code/03_webSever目录下执行mkdir www命令,创建网站目录,然后在其中创建index.htm和login.htm两个 HTML 文件以及一个名为style.css的 CSS 文件:

1、index.htm:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>首页</title>
</head>
<body>
<h1>你好,nodejs!</h1>
<p> <a href="login.htm">请登录!</a> </p>
</body>
</html>

2、login.htm:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>登录页面</title>
</head>
<body>
<h1>你已经登录。。。</h1>
<p> <a href="index.htm">回首页!</a> </p>
</body>
</html>

3、style.css:

body { 
background: gray; 
}

2、在code/03_webSever目录下执行touch 03-webServer.js命令,创建脚本文件,并输入如下代码:

const http = require('http')
const fs = require('fs')
const server = http.createServer()

server.on('request', function(req, res) {
const webRoot = './www'
const url = req.url
if ( url === '/' ) {
url = '/index.htm'
}

fs.readFile(webRoot+url, function(err, data) {
if ( err !== null ) {
console.error('错误信息:' + err.message)
return res.end('<h1>404 页面没找到!</h1>')
}
res.end(data)
})
})

server.listen(8080, function(){
console.log('请访问http://localhost:8080/,按Ctrl+C终止服务!')
})

3、保存所有文件后,在code/03_webSever目录下执行node 03-webServer.js命令,然后打开浏览器并访问http://localhost:8080/,就会看到如下页面:

示例4. 使用art-template模版引擎生成网页

这一部分本示例将以生成个人信息页面为例,演示在服务器端基于 Node.js 使用art-template模板引擎来生成网页。为此,我们需要在code目录下执行mkdir 04_templatingEngine命令来创建用于存放这一组示例的目录。

1. 单模版渲染

首先来示范一下如何使用art-template模版引擎的渲染单一模版文件,请跟着以下步骤来构建示例:

  1. 在code/04_templatingEngine目录下执行npm install art-template --save命令,安装将art-template包安装到当前示例项目中。
  2. 在code/04_templatingEngine目录下执行touch singleTpl.htm命令,创建一个模版文件,并在其中输入以下代码:
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>{{ name }}的个人信息</title>
</head>
<body>
<h1>{{ name }}的个人信息</h1>
<table>
<tr><td>姓名:</td><td>{{ name }}</td></tr>
<tr><td>年龄:</td><td>{{ age }}</td></tr>
<tr><td>性别:</td><td>{{ sex }}</td></tr>
<tr>
<td>爱好:</td>
<td>{{ each items }} {{ $value }} {{ /each }}</td>
</tr>
</table>
</body>
</html>

3、在code/04_templatingEngine目录下执行touch 04-useTemplating_engine.js命令,创建一个脚本文件,具体如下:

const http = require('http')
const fs = require('fs')
const template = require('art-template')

class human {
constructor(name, age, sex, items=[])
{
this.name = name
this.age = age
this.sex = sex
this.items = items
}
}

const server = http.createServer()

server.on('request', function(req, res){
const url = req.url
let boy = null
if ( url === '/' ) {
boy = new human('凌杰', '37', '男', ['看书', '看电影','旅游'])
} else if ( url === '/wang' ) {
boy = new human('蔓儿', '25', '女', ['看书', '看电影','写作'])
}

if ( boy === null ) {
return res.end('<h1>404 页面没找到!</h1>')
}

fs.readFile('./singleTpl.htm', function(err, data){
if ( err !== null ) {
return res.end('<h1>404 没找到模版文件!</h1>')
}

const strHtml = template.render(data.toString(), {
name : boy.name,
age : boy.age,
sex : boy.sex,
items: boy.items
})

res.end(strHtml)
})
})

server.listen(8080, function(){
console.log('请访问http://localhost:8080/,按Ctrl+C终止服务!')
})

4、保存所有文件后,在code/04_templatingEngine目录下执行node 04-useTemplating_engine.js命令,然后打开浏览器并访问http://localhost:8080/wang,就会看到如下页面:

2. 多模版组合渲染

在同一 Web 应用中,所有的页面通常都由相同的头部和底部元素,所以为了减少代码的冗余,提高重用率,开发者们通常会考虑将重复的部分独立成一个单独的模版文件,然后用相互包含的方式组合成页面。下面就继续以art-template模板引擎为例来演示一下如何将多个模版组合渲染成单一的 HTML 页面,其具体步骤如下:

  1. 在code/04_templatingEngine目录下执行touch tpl1.art tpl2.art命令,创建两个模版文件,然后在这两个文件中分别输入以下代码:

1、tpl1.art :

<header>
<h1>查看个人信息</h1>
<br>
</header>

2、tpl2.art :

<footer>
<div>
<p>© 2016 owlman.org;本站系纯HTML5站点。</p>
</div>
</footer>

2、在code/04_templatingEngine目录下执行touch multiTpl.htm命令创建用于组合的 HTML 页面文件,并在其中输入以下代码:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>查看个人信息</title>
</head>
<body>
{{ include './tpl1.art' }}
<h2>{{ name }}的个人信息</h2>
<table>
<tr><td>姓名:</td><td>{{ name }}</td></tr>
<tr><td>年龄:</td><td>{{ age }}</td></tr>
<tr><td>性别:</td><td>{{ sex }}</td></tr>
<tr>
<td>爱好:</td>
<td>{{ each items }} {{ $value }} {{ /each }}</td>
</tr>
</table>
{{ include './tpl2.art' }}
</body>
</html>

3、在code/04_templatingEngine目录下执行

cp 04-useTemplating_engine.js 04-useTemplating_engine2.js命令,将之前的代码复制一份,并修改如下:

const http = require('http')
const fs = require('fs')
const template = require('art-template')

template.defaults.root = __dirname // 配置模版的查找根目录

class human {
constructor(name, age, sex, items=[])
{
this.name = name
this.age = age
this.sex = sex
this.items = items
}
}

const server = http.createServer()

server.on('request', function(req, res){
const url = req.url
let boy = null
if ( url === '/' ) {
boy = new human('凌杰', '37', '男', ['看书', '看电影','旅游'])
} else if ( url === '/wang' ) {
boy = new human('蔓儿', '25', '女', ['看书', '看电影','写作'])
}

if ( boy === null ) {
return res.end('<h1>404 页面没找到!</h1>')
}

fs.readFile('./multiTpl.htm', function(err, data){ // 修改了要读取的模版文件
if ( err !== null ) {
return res.end('<h1>404 没找到模版文件!</h1>')
}

const strHtml = template.render(data.toString(), {
name : boy.name,
age : boy.age,
sex : boy.sex,
items: boy.items
})

res.end(strHtml)
})
})

server.listen(8080, function(){
console.log('请访问http://localhost:8080/,按Ctrl+C终止服务!')
})

4、保存所有文件后,在code/04_templatingEngine目录下执行node 04-useTemplating_engine2.js命令,然后打开浏览器并访问http://localhost:8080,就会看到如下页面:

3. 多模版继承渲染

当然,如果重复的元素只有头部和尾部的话,有时候使用模版继承语法来渲染页面会是一个更好的选择,下面就来继续演示一下art-template模板引擎的继承语法来渲染 HTML 页面,其具体步骤如下:

  1. 在code/04_templatingEngine目录下执行touch baseTpl.art命令,创建父模版文件,然后在该文件中输入以下代码:
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>{{ name }}的个人信息</title>
</head>
<body>
<header>
<h1>查看个人信息</h1>
<br>
</header>

{{ block 'message' }}
{{ /block }}

<footer>
<div>
<p>© 2016 owlman.org;本站系纯HTML5站点。</p>
</div>
</footer>
</body>
</html>

2、在code/04_templatingEngine目录下执行touch extendTpl.htm命令,创建子模版文件,然后在该文件中输入以下代码:

{{ extend 'baseTpl.art' }}

{{ block 'message' }}
<h1>{{ name }}的个人信息</h1>
<table>
<tr><td>姓名:</td><td>{{ name }}</td></tr>
<tr><td>年龄:</td><td>{{ age }}</td></tr>
<tr><td>性别:</td><td>{{ sex }}</td></tr>
<tr>
<td>爱好:</td>
<td>{{ each items }} {{ $value }} {{ /each }}</td>
</tr>
</table>
{{ /block }}

3、在code/04_templatingEngine目录下执行cp 04-useTemplating_engine.js 04-useTemplating_engine3.js命令,将之前的代码复制一份,并修改如下:

// 用Node.js生成动态页面
// 作者:owlman
// 时间:2019年07月12日

const http = require('http')
const fs = require('fs')
const template = require('art-template')

template.defaults.root = __dirname

class human {
constructor(name, age, sex, items=[])
{
this.name = name
this.age = age
this.sex = sex
this.items = items
}
}

const server = http.createServer()

server.on('request', function(req, res) {
const url = req.url
let boy = null
if (url === '/') {
boy = new human('凌杰', '37', '男', ['看书', '看电影','旅游'])
} else if (url === '/wang') {
boy = new human('蔓儿', '25', '女', ['看书', '看电影','写作'])
}

if (boy === null) {
return res.end('<h1>404 页面没找到!</h1>')
}

fs.readFile('./extendTpl.htm', function(err, data) {
if ( err !== null ) {
return res.end('<h1>404 没找到模版文件!</h1>')
}

const strHtml = template.render(data.toString(), {
name : boy.name,
age : boy.age,
sex : boy.sex,
items: boy.items
})

res.end(strHtml)
})
})

server.listen(8080, function(){
console.log('请访问http://localhost:8080/,按Ctrl+C终止服务!')
})

4、保存所有文件后,在code/04_templatingEngine目录下执行node 04-useTemplating_engine3.js命令,然后打开浏览器并访问http://localhost:8080,就会看到与之前相同的页面。

示例5. Web 表单处理

这一部分示例将致力于演示用 Node.js 处理 Web 表单,我们将会分别示范如何用get和post两种方法来处理表单的请求。首先,我们要在code目录下执行mkdir 05_webForm命令来创建用于存放这一组示例的目录。

1. get 方法

先用一个信息查询程序来演示一下如何处理使用get方法来发送请求的表单。首先,在code/05_webForm目录下执行mkdir get_form命令,并执行以下步骤:

在code/05_webForm/get_form目录下执行npm install art-template命令,将art-template安装到当前示例项目中。
在code/05_webForm/get_form目录下执行touch index.htm,创建一个模版文件,具体如下: <!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>个人信息查询</title>
</head>
<body>
<h1>个人信息查询</h1>
<form action="/query" method="GET">
<label for="message">请输入要查询的姓名:</label>
<input type="text" name="qname" />
<input type="submit" value="查询" />
</form>
<br />
{{ if name }}
<table>
<caption>{{ name }}的个人信息</caption>
<tr><td>姓名:</td><td>{{ name }}</td></tr>
<tr><td>年龄:</td><td>{{ age }}</td></tr>
<tr><td>性别:</td><td>{{ sex }}</td></tr>
<tr>
<td>爱好:</td>
<td>{{ each items }} {{ $value }} {{ /each }}</td>
</tr>
</table>
{{ else if query_error }}
<h2>没有找到相关信息!</h2>
{{ /if }}
</body>
</html>

3、在code/05_webForm/get_form目录下执行touch app.js,创建一个脚本文件,具体如下: const http = require('http')

const fs = require('fs')
const url = require('url')
const template = require('art-template')

class human {
constructor(name, age, sex, items=[])
{
this.name = name
this.age = age
this.sex = sex
this.items = items
}
}

const db = [
new human('凌杰', '37', '男', ['看书', '看电影','旅游']),
new human('蔓儿', '25', '女', ['看书', '看电影','写作']),
new human('张语', '32', '女', ['看书', '旅游','绘画'])
]

const server = http.createServer(function(req, res){
const query = url.parse(req.url, true)
let obj = null
let query_error = false
if ( query.pathname === '/' ) {
query_error = false
}
else if (query.pathname === '/query') {
for(let i = 0; i < db.length; ++i) {
if (db[i].name == query.query["qname"]) {
obj = db[i]
}
}
if ( obj === null ) {
query_error = true
}
} else {
return res.end('<h1>404 页面没找到!</h1>')
}

fs.readFile('./index.htm', function(err, data){
if ( err !== null ) {
return res.end('<h1>404 没找到模版文件!</h1>')
}

let strHtml = null
if ( obj !== null ) {
strHtml = template.render(data.toString(), {
name : obj.name,
age : obj.age,
sex : obj.sex,
items: obj.items,
query_error: query_error
})
} else {
strHtml = template.render(data.toString(), {
name : false,
query_error: query_error
})
}
res.end(strHtml)
})
})

server.listen(8080, function() {
console.log('请访问http://localhost:8080/,按Ctrl+C终止服务!')
})

4、保存所有文件后,在code/05_webForm/get_form目录下执行node app.js命令,结果如下:

2. post 方法

先来演示如何处理使用post方法来发送请求的表单。首先,在code/05_webForm目录下执行mkdir post_form命令,并执行以下步骤:

  1. 在code/05_webForm/get_form目录下执行npm install art-template命令,将art-template安装到当前示例项目中。
  2. 在code/05_webForm/post_form目录下执行touch index.htm,创建一个模版文件,具体如下:
 <!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>个人信息管理</title>
</head>
<body>
<h1>个人信息管理</h1>
<table>
<caption>个人数据表</caption>
<tr><th>姓名</th><th>年龄</th><th>性别</th><th>爱好</th></tr>
{{ each db }}
<tr>
<td>{{ $value.name }} </td>
<td>{{ $value.age }} </td>
<td>{{ $value.sex }} </td>
<td>{{ each $value.items }} {{ $value }} {{ /each }}</td>
</tr>
{{ /each }}
</table>

<form action="/add" method="POST">
<table>
<caption>录入新人员</caption>
<tr><td>姓名:</td><td><input type="text" name="uname" /></td></tr>
<tr><td>年龄:</td><td><input type="text" name="age"></td></tr>
<tr><td>性别:</td><td><input type="text" name="sex"></td></tr>
<tr><td>爱好:</td><td><input type="text" name="items"></td></tr>
</table>
<input type="submit" value="添加" />
</form>
</body>
</html>

3、在code/05_webForm/post_form目录下执行touch app.js,创建一个脚本文件,具体如下:

const http = require('http')
const fs = require('fs')
const url = require('url')
const querystring = require('querystring')
const template = require('art-template')

class human {
constructor(name, age, sex, items=[])
{
this.name = name
this.age = age
this.sex = sex
this.items = items
}
}

const db = [
new human('凌杰', '37', '男', ['看书', '看电影','旅游']),
new human('蔓儿', '25', '女', ['看书', '看电影','写作']),
new human('张语', '32', '女', ['看书', '旅游','绘画'])
]

const server = http.createServer(function(req, res){
const query = url.parse(req.url, true)
if ( query.pathname === '/' ) {
fs.readFile('./index.htm', function(err, data) {
if ( err !== null ) {
return res.end('<h1>404 没找到模版文件!</h1>')
}

const strHtml = template.render(data.toString(), {
"db": db
})

res.end(strHtml)
})
}
else if ( query.pathname === '/add' ) {
req.on('data', function(chunk) {
const obj = querystring.parse(chunk.toString())
db.push(new human(
obj['uname'],
obj['age'],
obj['sex'],
obj['items'].split(','),
))
})

res.writeHead(302, {
'location': `/`
})

res.end()
} else {
return res.end('<h1>404 页面没找到!</h1>')
}
})

server.listen(8080, function(){
console.log('请访问http://localhost:8080/,按Ctrl+C终止服务!')
})

4、保存所有文件后,在code/05_webForm/post_form目录下执行node app.js命令,结果如下:

、什么是 node.js?

① Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型。

② Node 是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服务端语言平起平坐的脚本语言。

2、安装 node.js

官网链接:

https://nodejs.org/zh-cn/

安装完成在终端里输入 node -v

当出现对应的 node 版本号,即安装成功。

下面执行 js 方法就是一贯通用的用 node 名字.js

3、全局函数

全局函数:简单理解就是放在 js 中任何地方都能执行。像 setTimeout 和 console 就是全局函数。

箭头函数:又叫匿名函数,简化函数的写法。箭头函数的好处:解决了this在function为undefined的问题。


4、回调函数

有个比方说的很形象,有一家旅馆提供叫醒服务,但是要求旅客自己决定叫醒的方法。可以是打客房电话,也可以是派服务员去敲门,睡得死怕耽误事的,还可以要求往自己头上浇盆水。这里,“叫醒”这个行为是旅馆提供的,相当于库函数,但是叫醒的方式是由旅客决定并告诉旅馆的,也就是回调函数。而旅客告诉旅馆怎么叫醒自己的动作,也就是把回调函数传入库函数的动作,称为登记回调函数。

5、导出和导入模块

① 导入单个函数

为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。

app.js

以上实例中,代码 require('./count_module') 引入了当前目录下的 count_module.js 文件(./ 为当前目录,node.js 默认后缀为 js)。

Node.js 提供了 exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。

count_module.js

在以上示例中,count_module.js 通过 exports 对象把 counter 作为模块的访问接口,在 app.js 中通过 require('./count_module') 加载这个模块,然后就可以直接访 问 count_module.js 中 exports 对象的成员函数了。

在终端执行 node app.js 输出:

② 导入多个函数

app.js


count_module.js

6、事件

7、文件读写

8、删除文件和创建文件夹

9、web 服务器

app.js

输出:

网页:

10、路由

① 入口文件

app.js

② server_路由.js

11、路由重构代码

app.js

server_重构路由.js

router.js

handler.js

过一个阶段测试,终于找到两个 markdown 转 html 并实现代码高亮的工具,并以最简代码(几十行)实现了炫酷的展示效果。步骤很少,也很简单,零基础也应该一看就会。往下看吧......,需要安装有Node环境哦!

1 缘起

因为markdown 文档编辑器具有语法简单、文件简洁、标准化、使用广泛等特点,所以一直习惯采用 markdown 编辑器写文章,但仍有一些网站不支持 markdown 编辑器,想尝试将 markdown 转成 html 再发布,采用 Javascript 来实现,尤其想达到 CSDN 博客、简书这样的展示效果。

图1 CSDN 博客 markdown 文章及代码块高亮效果

图2 简书 markdown 文章及代码高亮效果

2 插件选择及应用模式

2.1 插件选择

2.1.1 markdown 转 html 插件

比较常用的 M2H 插件有:

  • Markdown-it 中文:https://markdown-it.docschina.org/ github:https://github.com/markdown-it/markdown-it
  • Marked 官网:https://marked.js.org/ github:https://github.com/markedjs/marked

从网上获得的 markdown-it 和 marked 的比较,主要表现在:在性能、使用简单程度、正则解析(中文支持)方面,marked 比较好;在扩展性上,markdown-it 表现则更好一些。 由于 markdown 应用比较成熟,而且一般使用也不会太复杂,所以选择性能好、中文支持好的 marked,至于 marked 的扩展性,也尝试了一下,满足常见的应用是没问题的。

2.1.2 代码块高亮模块

代码块高亮插件有:

  • heiglightjs 官网:https://highlightjs.org/ github:https://github.com/highlightjs/highlight.js
  • prismjs 官网:https://prismjs.com/ github:https://github.com/PrismJS/prism

对 heiglightjs 和 prismjs 分别做了简单测试,发现 prismjs 使用非常简单,易于上手,且代码精简,效率高,而 heiglightjs 相对比较复杂,使用起来不习惯,也许是各人喜好不同吧。所以选择使用 prismjs 插件。

2.2 插件应用模式

M2H 一般有两种应用模式:一种是前端渲染,如在 vue 中使用;另一种是在后端生成 html 文件,在浏览器展示,如在 node 中使用。 此处我选择在 node 中生产静态 html 文件的应用模式,用户可以在电脑端当作 markdown 转 node 的工具使用; 至于前端渲染,vue 页面打包时总会包含一个 chunk-vendors.js 文件,会引起页面加载变慢,有很多办法压缩该文件,但这已经超出了 M2H 的范畴了,在此不再赘述。

3 计划实现的功能

  • 读取指定 mardown 文件(test.md),生成目标 html 文件(test.html)——测试 marked 插件解析及渲染功能
  • html 文件根据代码块对应的语言进行高亮显示——测试 prismjs 插件的 language 语言包功能
  • html 文件实现显示语言名称、“复制”按钮、行号——测试 prismjs 插件的 Plugins 功能
  • 自定义代码块的显示样式修改——测试拓展功能
  • 最终实现的界面如下图:

图3 最终实现的markdown 转化及代码块渲染效果

4 编码实现

4.1 准备工作

4.1.1 创建项目

创建目录:marked-prismjs,使用 vsCode 打开该目录。

4.1.2 安装插件

在 vsCode 里的终端输入相关命令进行插件安装 1)安装 marked 插件

npm install marked --save

2)安装 prismjs

npm install prismjs --save

4.1.3 下载 prismjs 的 css 和 js 文件

访问官网下载页:https://prismjs.com/download.html

  • 按下图选择 themes,我比较喜欢“Tomorrow Night” 这个主题,您可以根据自己的喜好选择

图4 themes 选项

  • Languages 选项,默认即可,如下图,其中包含 CSS、Javascript 语言

图5 编程语言包选项

  • Plugins 选项,可以根据功能需要选择,此处选择4个选项,依次为:行号、显示语言名称、工具条、复制到剪贴板的按钮,如下图:

图6 插件选项

  • 分别点击下图的“DOWNLOAD JS”和“DOWNLOAD CSS”按钮下载 prism.js 和 prism.css 到项目根目录下。

4.1.4 编写 markdown 测试文件

  • 编写 markdown 测试文件:test.md,内容如下:

# 这是H1标签

## 下面是 javascript 代码:

```javascript let a = 1; console.log(a); ```

4.2 编写实现转换功能的 js 文件

创建 m2h.js 文件,内容为:

const { marked } = require('marked') // 引入 marked 模块
const prism = require('prismjs') // 引入 prism 模块
const fs = require('fs') // 引入文件处理模块
const mdContent = fs.readFileSync('test.md', 'utf-8') // 读取 markdown 文件内容
// 下面是 marked 扩展功能,当节点(token)类型是代码(code)时,自定义渲染节点功能,及使用自定义的 renderer 函数来代替默认 renderer 函数,达到改写当前节点生成的 html 代码的样式
marked.use({
    extensions: [{
        name: 'code',   
        renderer(token) {
            if (token.type === 'code') {
                let codeHtml = `<pre class="language- round"><code class="language-`+token.lang+` line-numbers">`
                codeHtml+=Prism.highlight(token.text, Prism.languages.javascript, 'javascript')
                codeHtml+=`</code></pre>`
                return codeHtml
            }
        }
    }]
})
// 定义 html 文件头部代码
var htmlContent=`
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="prism.css">
    <script src="prism.js"></script>
</head>
<style>
  .round {
    box-shadow: 10px 10px 5px #888888;
    border-radius: 10px;
  }
</style>
<body>
`
htmlContent += marked.parse(mdContent) // 叠加上 marked 生成的 html 代码
htmlContent+=`</body> // 叠加底部代码(补齐)
</html>`
fs.writeFileSync('test.html', htmlContent) // 将最终的 html 内容写入到文件 test.html

测试运行:

node m2h.js

每运行一次,就会重新生成新的 test.html 文件。

在 vsCode 里鼠标右键点击 test.html 文件,选择“Open with Live Server”,

图7 Open with LiveServer

会在浏览器里打开 test.html 页面,test.md 已经成功生成了 test.html,实现了代码块高亮、语言显示及拷贝按钮及行号。得到的最终结果如下图:

图8 效果展示

达到了当初计划实现的功能需求。

5 总结

以上通过简单的几十行代码就实现了如此炫酷的功能展示,体现了插件的强大功能,同时通过自定义扩展节点渲染函数,也展现了插件的灵活性和可扩展性。此次测试仅仅是个引子,后续会继续进行研究和测试,感兴趣请收藏、关注,方便共同学习、进步。