整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Node.js 學習筆記:構建 Web 服務

          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-RED的功能,應用場景、安裝、配置及基本使用。那今天將繼續深入高級用法,還有初步實現原理。這樣的話,就可以對Node-RED更深入的掌握,可以更加靈活應用起來。如果默認的功能如果不能滿足需求,我會介紹擴展方法,大家熟悉了就可以定制自己的流式處理程序了。我已經把它移植到了邊緣計算網關當中了,充當規則引擎。你們也充分發揮想象力,盡情發揮它的威力。

          1. 節點說明:

          我們挑選一些重點的節點做下說明。

          • 輸入節點:flow的數據來源,入口。通過各種網絡協議,手工注入,串口等方式注入數據。
          • 處理節點:某些專門用來在處理數據,比如HTML解析,數據轉換,拼接等等。在節點的javascript block中完成。此類節點就是處理節點。
          • 輸出節點:按照某種協議,規范,進行數據輸出。比如可以是websocket, TCP, UDP,HTTP response。
          • 社交節點:用來email收發,twitter等社交工具連接。比如可以從輸入節點接收數據,通過email節點,就可以發送到163郵箱當中。
          • 其它幾點:比如下列表格中列出的高級節點,硬件節點等等,都是功能的封裝。

          節點類型

          節點名稱

          節點說明







          輸入

          Inject

          注入節點,向flow中注入payload

          Catch

          捕獲節點異常

          Status

          從其它節點發送狀態消息

          MQTT

          MQTT節點消息輸入節點

          HTTP

          HTTP 請求輸入節點

          Web socket

          Web socket協議輸入節點

          TCP

          TCP協議輸入節點

          UDP

          UDP協議輸出節點

          Serial

          串口數據輸入節點

          處理


          Template

          按照預制的模板,設置message屬性,或者數據轉換

          Delay

          增加延時

          Function

          用戶直接編寫javascript處理函數。

          Change

          可以對payload進行搜索替換

          社交

          email

          發送郵件

          twitter

          發送twitter消息

          存儲

          file

          用來將信息保存到文件當中。

          高級

          exec

          可以設置調用執行的命令,或者腳本

          Raspberry Pi

          rpi gpio

          控制樹莓派GPIO端口。輸入或者輸出兩種

          rpi mouse

          控制樹莓派鼠標控制。

          rpi keyboard

          樹莓派鍵盤控制。

          在使用的時候,上面的Node應該可以滿足的大部分應用了。

          2.自定義節點

          Node-Red除了系統內置的節點,還提供了自定義節點的功能,是它的一大特點。具體文檔參考:https://nodered.org/docs/creating-nodes/first-node.html

          場景:當系統默認組件功能不足,用戶需要個性化功能,外觀設置的時候,就會用到。

          可以把npm module封裝為node.每個node包含兩部分:

          • .js 定義了server端的行為。
          • .html定義了界面中編輯器的外觀及幫助。

          該模塊可以通過npm安裝到Node-Red當中。

          JS文件中需要完成:

          1. 創建節點,注冊節點類型。

          注冊節點類型

          2.定義如何接收消息

          定義如何接收消息

          3.定義如何發送消息


          定義如何發送消息

          還有如何關閉節點,在節點日志處理,國際化等操作。官方文檔中做了非常詳細的說明。


          3.在線Node及Flow

          Node-Red除了提供可視化編輯器以外,自己動手創建flow。還有一個強大的在線社區,上面已經提供大量資源。包括Node與Flow。我們在使用Node-Red的過程中,首先搜索一下是不是已經有現成的Node, Flow可以用。打開:https://flows.nodered.org 就可以訪問到在線資源。比如,在工業里常用的modbus協議,我們看看如何支持:

          搜索Node節點


          安裝modbus節點

          點擊進去就可以訪問到該node的詳細信息。告訴用戶如何安裝,如何使用。安裝完成后,重啟Node-Red就可以使用了。

          4.綜合例子

          綜合例子中我們綜合MQTT輸入,email節點。來看復雜一些的flow創建及執行過程。在我們日常的使用過程中,大部分就是這種場景。

          MQTT處理流程,Node-RED處理MQTT消息體,進行預警

          • Device通過MQTT協議上報數據。
          • 發送到MQTT Broker。
          • 在Node-Red輸入節點中,進行MQTT消息訂閱,當有訂閱消息收到時,會接收消息并打包到message中,經過Function節點進行處理。當超過某一閥值時,會流轉到email節點。通過email節點發送通知郵件。

          這就是一個典型的物聯網+Node-RED應用。Node-RED充當了物聯網平臺的規則引擎。這是放在云端。當然把它放在硬件網關中,充當邊緣計算引擎也是可以的。大家可以動手親自試一下。要是有問題,可以留言或者自私。

          今天的介紹就到這里。下一期,我將帶大家深入Node-RED內部工作機制,以及源代碼分析。可以幫助大家透徹了解它。 其實這個軟件,大家可以充分發揮想象力,它能干的事情非常多。日常工作,可以定制為各種商業化軟件。

          過一個階段測試,終于找到兩個 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 總結

          以上通過簡單的幾十行代碼就實現了如此炫酷的功能展示,體現了插件的強大功能,同時通過自定義擴展節點渲染函數,也展現了插件的靈活性和可擴展性。此次測試僅僅是個引子,后續會繼續進行研究和測試,感興趣請收藏、關注,方便共同學習、進步。


          主站蜘蛛池模板: 中文字幕一区二区三区日韩精品| 亚洲AV永久无码精品一区二区国产| 免费无码一区二区三区| 日韩制服国产精品一区| 久久亚洲综合色一区二区三区| 91在线一区二区三区| 色一情一乱一区二区三区啪啪高| 国产一区二区好的精华液| 日本中文字幕在线视频一区| 精品少妇一区二区三区视频| 蜜桃无码一区二区三区| 在线观看一区二区三区视频| 天天看高清无码一区二区三区| 波多野结衣免费一区视频| 国产主播福利一区二区| 一区二区免费国产在线观看| 日韩在线不卡免费视频一区| 日本精品一区二区三本中文| 亚洲乱码一区二区三区在线观看 | 一区二区三区高清| 日韩精品一区在线| 精品一区二区在线观看| 国产精品日韩欧美一区二区三区| 一区二区三区无码高清| 亚洲Av无码一区二区二三区| jizz免费一区二区三区| 亚洲国产美女福利直播秀一区二区| 日本精品视频一区二区三区| 蜜桃臀无码内射一区二区三区| 国产亚洲福利精品一区二区| 日韩一区二区三区无码影院| 国产成人精品a视频一区| 无码福利一区二区三区| 精品亚洲一区二区三区在线观看| 男插女高潮一区二区| 国产综合一区二区| 全国精品一区二区在线观看| 在线成人一区二区| 天堂资源中文最新版在线一区| 午夜无码视频一区二区三区| 亚洲综合av一区二区三区|