简单的markdown在线解析服务

说明

之前要写一个项目文档,需要给上级审核之后才能push到线上。直接扔markdown文件有些不合适,但将它转为pdf文件发送有点麻烦,每次修改都需要转一次,再发送。因此就有了写一个简单的markdown在线解析服务的想法。到时候直接给地址,意见反馈后,直接本地修改,服务更新后就能看到新版本了。

dependences

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

文件目录

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

接口

  • / index显示扫描到的文件列表
  • /read?file=${fileName} 显示markdown转换后的HTML页面
  • /update 调用后,重新扫描文件目录

实现

··· 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接口更新的问题。

猜你喜欢

转载自my.oschina.net/u/3703365/blog/1802127