node-framework
Version:
node-framework
197 lines (166 loc) • 5.03 kB
JavaScript
/**
* @file wiki.js
* @author sekiyika (px.pengxing@gmail.com)
* @description
*
*/
var util = require('util');
var fs = require('fs');
var path = require('path');
var marked = require('marked');
var _ = require('lodash');
var Controller = require('../../index').Controller;
marked.setOptions({
gfm: true,
tables: true,
breaks: true,
pedantic: false,
sanitize: true,
smartLists: true,
smartypants: true,
highlight: function (code, lang) {
return require('highlight.js').highlightAuto(code, [lang]).value;
}
});
var renderer = new marked.Renderer();
renderer.heading = function (text, level) {
var escapedText = escape(text);
return '<h' + level + '><a name="' +
escapedText +
'" class="anchor" href="#' +
escapedText +
'"><span class="icon icon-paragraph"></span></a>' +
escapedText + '</h' + level + '>';
};
renderer.tablecell = function (content, flags) {
var extraClazzRule = /\s*(.+?)\(@CLASS=(.+?)\)\s*/g;
var type = flags.header ? 'th' : 'td';
var tag = flags.align
? '<' + type + ' style="text-align:' + flags.align + '">'
: '<' + type + '>';
if (extraClazzRule.test(content)) {
var matchArr = content.match(extraClazzRule);
content = [];
for (var i in matchArr) {
var tmp = matchArr[i].match(/\s*(.+?)\(@CLASS=(.+?)\)\s*/);
content.push('<span class="' + tmp[2] + '">' + tmp[1] + '</span>');
}
content = content.join('');
}
if (~content.indexOf('(@BR)')) {
content = content.replace(/\(@BR\)/g, '<br/>');
}
return tag + content + '</' + type + '>\n';
};
function Wiki() {
Controller.apply(this, Array.prototype.slice.call(arguments, 0));
}
util.inherits(Wiki, Controller);
Wiki.prototype.actionIndex = function () {
var filename = this.req.param(0);
if (!filename) {
filename = 'index';
}
var baseDir = this.app.config.global.appdir;
filename = filename + '.md';
var filepath = path.join(baseDir, 'docs', filename);
if (!fs.existsSync(filepath)) {
// TODO 404
this.send('Not Found');
return;
}
var meta;
var index;
var list = this.app.scan();
for (var i = 0, l = list.length; i < l; i++) {
if (filename === list[i].file) {
meta = list[i];
index = i;
break;
}
}
var text = fs.readFileSync(filepath).toString();
var data = {
previous_page: false,
next_page: false
};
_.merge(data, this.app.config.wiki);
data.page_title = meta.pageTitle;
var filenames = filename.split(path.sep);
data.current_page = {
file: filename,
title: meta.pageTitle
};
if (filenames.length === 2) {
data.current_page.folder = filenames[0];
}
if (index > 0) {
var item = list[index - 1];
data.previous_page = {
title: item.pageTitle,
url: '/' + item.file.substring(0, item.file.length - 3)
}
}
if (index < (list.length - 1)) {
item = list[index + 1];
data.next_page = {
title: item.pageTitle,
url: '/' + item.file.substring(0, item.file.length - 3)
}
}
data.nav = this.getNav();
data.content = marked(text, {
renderer: renderer
});
this.render('base', data);
};
Wiki.prototype.getNav = function () {
var me = this;
var list = me.app.scan();
var result = [];
var recordedList = {};
list.forEach(function (item) {
var data = {
children: []
};
// 文件目录目前最多支持两级
var file = item.file;
var files = file.split('/');
if (files.length > 2) {
me.app.logger.warn(files + ' exceed two layers.');
return;
} else if (files.length === 2) {
var folder = files[0];
if (recordedList[folder] === undefined) {
recordedList[folder] = result.length;
data.title = folder;
data.folder = folder;
result.push(data);
}
data = result[recordedList[folder]];
data.children.push({
url: '/' + item.file.substring(0, item.file.length - 3),
title: item.pageTitle,
file: item.file,
tocTree: item.tocTree
});
} else {
data.url = '/' + item.file.substring(0, item.file.length - 3);
data.title = item.pageTitle;
data.file = item.file;
data.tocTree = item.tocTree;
result.push(data);
}
});
// console.log(result);
return result;
};
function escape(html) {
return String(html)
.replace(/&/g,'&')
.replace(/</g,'<')
.replace(/>/g,'>')
.replace(/"/g, """)
.replace(/'/g, "'");
}
module.exports = Wiki;