源碼地址: https://github.com/zhuangZhou/SimpleMarkdown
預(yù)覽地址: http://hawkzz.com:8000
作者網(wǎng)站:http://hawkzz.com
簡(jiǎn)介
這是一款基于NodeJs開(kāi)發(fā)的簡(jiǎn)單的Markdown編輯器,其UI是仿照簡(jiǎn)書(shū)的Markdown編輯器;主要功能:實(shí)時(shí)解析,實(shí)時(shí)保存,實(shí)時(shí)預(yù)覽,全屏等
預(yù)覽

技術(shù)棧
- NodeJs
- Express
- Swig
- Marked
- highJs
- Jquery
實(shí)時(shí)解析、保存
經(jīng)常使用簡(jiǎn)書(shū)的Markdown編輯器書(shū)寫(xiě)博客,它的有點(diǎn)很明顯,一是,可以實(shí)時(shí)保存,二是,可以實(shí)時(shí)解析;因?yàn)樽约合胱鰝€(gè)個(gè)人網(wǎng)站,其中就有書(shū)寫(xiě)博客功能,考慮過(guò)使用已經(jīng)目前很成熟的富文本編輯器,比如:ueditor編輯器;但是感覺(jué)這些編輯器都太過(guò)于龐大,于是,就有了自己寫(xiě)一個(gè)編輯器的念頭,說(shuō)干就干;研究了簡(jiǎn)書(shū)的Markdown編輯器的工作原理,它是怎么實(shí)現(xiàn)實(shí)時(shí)保存和解析的;然后開(kāi)始了自己的構(gòu)思。
想要實(shí)時(shí)保存,就需要不斷的給后臺(tái)傳輸數(shù)據(jù),那么是以什么頻率去給后臺(tái)傳輸數(shù)據(jù)呢?以什么樣的形式去保存呢,是直接保存在數(shù)據(jù)庫(kù),還是保存在一個(gè)文件里面呢?
首先,是第一個(gè)問(wèn)題,既然是實(shí)時(shí)保存,所以我這里是以每輸入一個(gè)字符,就開(kāi)始實(shí)時(shí)保存,這樣的一個(gè)缺點(diǎn)就是請(qǐng)求次數(shù)太多,如果各位有什么好建議,請(qǐng)拍磚;
然后,是第二個(gè)問(wèn)題,我這里是通過(guò)把標(biāo)題寫(xiě)在一個(gè)數(shù)組里(當(dāng)然在實(shí)際項(xiàng)目中這是寫(xiě)在數(shù)據(jù)庫(kù)里的,這里只是不想開(kāi)數(shù)據(jù)庫(kù),所以使用數(shù)組),文章放在一個(gè)文件里,通過(guò)標(biāo)題(或數(shù)據(jù)庫(kù)標(biāo)識(shí))來(lái)查詢(xún)文章;
下面為主要的NodeJs后臺(tái)代碼
router.post('/save', (req, res) => {
//獲取數(shù)據(jù)
let title = req.body.title;
let markdown = req.body.markdown;
let change = Number.parseInt(req.body.change);
let html = `# ${title} # \n ${markdown}`;
fs.exists('./docs/' + title + '.md', (exists) => {
console.log(exists);
if (!exists) {
console.log(change);
if (change === 1) {
let oldTitle = req.body.oldTitle;
fs.unlink('./docs/' + oldTitle + '.md', (err) => {
if (err) {
return console.error(err);
}
titleArr.forEach((item, index) => {
if (item === oldTitle) {
titleArr.splice(index, 1, title);
}
})
console.log('刪除成功!');
});
} else {
titleArr.splice(0, 0, title);
console.log(titleArr);
}
}
});
//寫(xiě)入文件
let writeStream = fs.createWriteStream('./docs/' + title + '.md');
writeStream.write(markdown);
writeStream.end();
writeStream.on('finish', () => {
console.log('寫(xiě)入完成');
});
//傳遞數(shù)據(jù)
let data = {};
data.html = marked(html);
res.json(data);
});
前臺(tái)代碼:
//實(shí)時(shí)保存解析文檔
function transformMd() {
var markdown = $('#editArea').val();
var title = $('#markTitle').val();
var oldTitle = $('#markTitle').attr('data-old');
var change = 0;
if (oldTitle != undefined && title != oldTitle) {
change = 1;
}
$.post('/save', {
markdown: markdown,
title: title,
oldTitle: oldTitle,
change: change
}, function (res) {
$('.right').html(res.html);
$('#markTitle').attr('data-old', title);
$('pre code').each(function (i, block) {
hljs.highlightBlock(block);
});
}, 'json');
}
后記
這篇博客只是介紹了核心功能,其余的感覺(jué)無(wú)需多介紹,需要了解的可以看源碼,都有注釋?zhuān)喽嗾徑猓。。?/p>
目前只是實(shí)現(xiàn)了新建文檔和實(shí)時(shí)解析,實(shí)時(shí)保存以及一些基本功能,還有一些構(gòu)思沒(méi)有實(shí)現(xiàn),比如:上傳文檔解析;敬請(qǐng)期待!?。?/p>