簡單的markdown在線解析服務

說明

以前要寫一個項目文檔,須要給上級審覈以後才能push到線上。直接扔markdown文件有些不合適,但將它轉爲pdf文件發送有點麻煩,每次修改都須要轉一次,再發送。所以就有了寫一個簡單的markdown在線解析服務的想法。在本地搭一個服務,到時候直接給地址,意見反饋後,直接本地修改,服務更新後就能看到新版本了。html

dependences

  • github.com/microcosm-cc/bluemonday
  • gopkg.in/russross/blackfriday.v2

文件目錄

  • ./markdowns/* 存放須要解析的markdown文件
  • ./templates/* 存放工程須要的html模板

接口

  • / index顯示掃描到的文件列表
  • /read?file=${fileName} 顯示markdown轉換後的HTML頁面
  • /update 調用後,從新掃描文件目錄

基本思路

簡單的在main.go裏增長一個全局以文件名稱爲key,具體路徑爲value的map。index頁面就遍歷這個map,read接口就從這裏獲取文件路徑,讀取返回。update也是更新這個表。後期若是增長緩存,將路徑string改成自定義的struck。git

實現

index.html模板

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <h1>markdownlist</h1>
  {{range $key, $value := .}}
  <a href="/read?file={{$key}}">{{$key}}</a><br/>
  {{end}}
</body>
</html>

main.go

package main

import (
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"github.com/microcosm-cc/bluemonday"
	"gopkg.in/russross/blackfriday.v2"
)

var (
	MARK_DOWNS_PATH = "markdowns"
	TEMPLATES_PATH  = "templates"
	fileMap         map[string]string
	globalLock      *sync.RWMutex
)

func init() {
	globalLock = new(sync.RWMutex)
	updateMarkdownFileList()
}

func updateMarkdownFileList() {
	globalLock.Lock()
	defer globalLock.Unlock()
	fileMap = make(map[string]string)
	files, _ := filepath.Glob(fmt.Sprintf("%s/*", MARK_DOWNS_PATH))
	for _, f := range files {
		fileName := f[strings.LastIndex(f, string(os.PathSeparator))+1 : len(f)-3]
		fileMap[fileName] = f
	}
}

func readMarkdownFile(fileName string) ([]byte, error) {
	globalLock.RLock()
	defer globalLock.RUnlock()
	markdownFile, ok := fileMap[fileName]
	if !ok {
		return nil, fmt.Errorf("file(%s)NotExist", fileName)
	}

	if fileread, err := ioutil.ReadFile(markdownFile); err == nil {
		unsafe := blackfriday.Run(fileread)
		html := bluemonday.UGCPolicy().SanitizeBytes(unsafe)
		return html, nil
	} else {
		return nil, fmt.Errorf("file(%s)ReadFail", fileName)
	}

}

func indexHandler(w http.ResponseWriter, r *http.Request) {
	t := template.New("index.html")
	t, _ = t.ParseFiles(fmt.Sprintf("%s%sindex.html", TEMPLATES_PATH, string(os.PathSeparator)))
	t.Execute(w, fileMap)
}

func readerHander(w http.ResponseWriter, r *http.Request) {
	name := r.URL.Query().Get("file")
	body, err := readMarkdownFile(name)
	if err != nil {
		w.WriteHeader(http.StatusNotFound)
	} else {
		w.Write(body)
	}
}
func updateHandler(w http.ResponseWriter, req *http.Request) {
	updateMarkdownFileList()
	w.Write([]byte("success"))
}
func main() {
	http.HandleFunc("/", indexHandler)
	http.HandleFunc("/read", readerHander)
	http.HandleFunc("/update", updateHandler)

	http.ListenAndServe(":8000", nil)
}

小結

項目的重點就在於markdown解析成html,既然都直接使用現成的第三方包,就基本沒有什麼技術性。惟一須要考慮的就是鎖的問題。後期還能夠增長緩存來提升性能,增長trylock限制update接口更新的問題。github

ennn

如下是新版本pro的代碼,主要是增長了一些鎖加強併發和易用性的東西,與功能無大關係 下載地址緩存

相關文章
相關標籤/搜索