我写书都是采用markdown格式,所以在这里我介绍几款md相关的写书系统。
写书的工具有很多gitbook,mkdocs等。
gitbook,是github推出的,目前已经不更新了,安装使用都会遇到一些版本兼容的bug。所以导致我无法使用。gitbook采用的编程语言是JavaScript。
mkdocs ,目前维护的非常好。material主题也很漂亮,采用Python语言编写。showdoc
showdoc 是php语言编写,
目前支持在线直接书写,免费版本有些限制。毕竟他们也是团队在开发。也需要支付服务器成本。所以收费也是必然的。
我没有试过收费版本。也无法评价。mrdoc
mrdoc 采用python编写,比较符合我的需求。开源可以安装使用。
并且支持在线写文档。也有开源版本和专业版。mindoc
是一款基于go语言编写的在线文档系统。MinDoc 的前身是 SmartWiki 文档系统。SmartWiki 是基于 PHP 框架 laravel 开发的一款文档管理系统。
如果要使用在线的系统,上面的都可以考虑。
自己打造一个,不是为了和他们竞争,是为了自己使用。
我写了几本书都是采用的mkdocs。非常喜欢使用mkdocs。
但是出现了一个问题,就是插入图片操作不方便。所以我想借助一个现成的在线系统去完成。
因为我经常使用strapi来做网站系统。strapi后台功能非常强大,并且支持markdown编写。所以我想让他们结合起来。
mkdocs是python,strapi是nodejs(javascript)。所以估计很多人也不愿意折腾。
不过在这里mkdocs仅仅需要安装即可,安装命令也简单
pip install mkdocs
strapi改造支持mkdocs需要2个步骤
- 创建一个表 支持 mkdocs.yml (ebook)
- 创建一个表支持mk文件 (file_md)
这就创建一条记录可以把mkdocs.yml 放到ebook表里面
再创建多条记录 *.md 房主 file_md表里
数据的表如何变成mkdocs需要的文件呢?
我写了一个解释代码
const fetch = require('node-fetch');
const YAML = require('yaml');
const fs = require('fs')
const path = require('path')
var exec = require("child_process").exec;
var host = "http://127.0.0.1:1337"
//var host = "http://119.91.153.63:1337"
// bookid
var bookid = 1
var filelist = []
// AIDocs/ oWriter/src/api/ebook/controllers
var father = path.resolve(__dirname,'../../../../')
var bookpath = path.resolve(father,'../tmp')
var bookdocpath = path.resolve(bookpath,'docs')
function parse_nav(n){
var val = Object.values(n)[0]
// filename
if(typeof val === 'string'){
console.log(val)
filelist.push(val)
} else{
//二级子目录,需要再次循环
val.forEach(function(item){
parse_nav(item)
})
}
}
async function make_filecontent(filename){
const file_parse = path.parse(filename)
const res = await fetch(host+"/api/file-mds?filters[filename][$eq]="+filename+"&filters[ebook][id][$eq]="+bookid)
const datas = await res.json()
if (datas.meta.pagination.total == 0) return
let content = datas.data[0].attributes.content
//console.log(file_parse.dir,file_parse.base)
let filepath = path.resolve(bookdocpath,file_parse.dir)
console.log(filepath)
//如果目录不存在创建目录,支持创建多级目录
if (!fs.existsSync(filepath)) fs.mkdirSync(filepath,{ recursive: true });
fs.writeFileSync(path.resolve(filepath,file_parse.base),content,{flag:"w+"})
return
}
async function bookupdate(ctx){
// 读取书的信息
const res = await fetch(host+"/api/ebooks")
var datas = await res.json()
var objdata = ""
for (var i = 0; i < datas.data.length;i++){
var data = datas.data[i]
if(data.id == bookid){
objdata = data
break
}
}
if (objdata == "") return
var buffer = objdata.attributes.yml
var name = objdata.attributes.name
var folder = objdata.attributes.folder
let config = YAML.parse(buffer);
var nav = config['nav']
if (folder != ""){
bookpath = path.resolve(father,'../'+folder)
bookdocpath = path.resolve(bookpath,'docs')
}
//创建mkdocs 项目配置文件
if (!fs.existsSync(bookpath)) fs.mkdirSync(bookpath,{ recursive: true });
fs.writeFileSync(path.resolve(bookpath,'mkdocs.yml'),buffer,{flag:"w+"})
nav.forEach(function(item){
parse_nav(item)
})
//创建所有的markdown 文件
console.log("---------------------------")
filelist.forEach(async function(item){
await make_filecontent(item)
})
exec("cd "+ bookpath +";mkdocs build",function(err,stdout,stderr){
if(err){
console.error(err);
}
console.log("stdout:",stdout)
console.log("stderr:",stderr);
});
}
strapi 编辑预览界面