QWiki/index.js

255 lines
7.3 KiB
JavaScript
Executable File

#!/usr/bin/env node
var fs = require('fs');
var m_path = require('path');
var util = require('util');
var QCore = require('./QCore.js');
/* qwiki
Node.js based Implementation of the proposed qwiki document
*/
/*********************************
* QWiki *
*********************************/
var QWiki = function() {
QCore.call(this);
this.initialize();
}; util.inherits(QWiki, QCore);
/* QWiki.initialize()
Checks for and creates the following directories:
* wiki/
* cache/
* tmp/
Checks for and copies the following directories/files:
* index.html
* acts/
*/
QWiki.prototype.listen = function(port, cb) {
this.loadWikiIndex();
this.constructor.super_.prototype.listen.call(this, port, cb);
};
QWiki.prototype.initialize = function() {
// check if QWiki instance is running in a different directory than the module,
// and if so, copy over default files
var cwd = process.cwd();
if (cwd !== __dirname) {
console.log('Running from: ' + cwd);
// TODO: copy acts/, wiki/, and index.html from __dirname to cwd if not existing
} else {
console.log('Running from: ' + __dirname);
}
// make wiki directory
try {
var stats = fs.statSync('wiki');
if (!stats.isDirectory()) {
console.log('error, "wiki" is not a directory');
}
} catch (err) {
if (err.code == 'ENOENT') {
fs.mkdirSync('wiki');
console.log('Created "wiki/" -- this is where the wiki source files are stored');
} else {
console.log('error while loading wiki directory');
}
}
// make cache directory
try {
var stats = fs.statSync('cache');
if (!stats.isDirectory()) {
console.log('error, "cache" is not a directory');
}
} catch (err) {
if (err.code == 'ENOENT') {
fs.mkdirSync('cache');
console.log('Created "cache/" -- this is where processed wiki pages are stored as HTML');
} else {
console.log('error while loading cache');
}
}
// make tmp directory
try {
var stats = fs.statSync('tmp');
if (!stats.isDirectory()) {
console.log('error, "tmp" is not a directory');
}
} catch (err) {
if (err.code == 'ENOENT') {
fs.mkdirSync('tmp');
console.log('Created "tmp/" -- this is where uploaded files are temporarily stored');
} else {
console.log('error while loading tmp directory');
}
}
};
QWiki.prototype.loadWikiIndex = function() {
var self = this;
try {
this.wiki_index = JSON.parse(fs.readFileSync('index.json'));
} catch (e) {
this.wiki_index = { pages: {} };
console.log(e);
}
var wiki_index = this.wiki_index;
console.log('loaded indices for ' + Object.keys(this.wiki_index.pages).length + ' pages');
QCore.prototype.readFiles('wiki', function(err, file, is_dir) {
var wiki_file = file.replace('wiki/', '');
if (is_dir) {
if (wiki_file in wiki_index.pages) {
if (wiki_index.pages[wiki_file].dir != true) wiki_index.pages[wiki_file].dir = true;
} else {
wiki_index.pages[wiki_file] = { dir: true };
}
} else {
if (QCore.prototype.getExt(file) == 'qwk') {
if (wiki_file in wiki_index.pages) {
} else {
var name = wiki_file.slice(0, -4);
wiki_index.pages[name] = { format: 'md' }; // TODO: this.config.default_type
}
} else {
if (wiki_file in wiki_index.pages) {
} else {
wiki_index.pages[wiki_file] = { format: 'file' };
}
}
}
});
}
QWiki.prototype.formats = {
raw: {
name: 'raw',
fullname: 'Raw',
convert: function(source) {
return source;
},
},
html: {
name: 'html',
fullname: 'HTML',
convert: function(source) {
return source;
}
}
};
QWiki.prototype.addFormat = function(name, fullname, convertor_cb, pre_cb, post_cb) {
this.formats[name] = {
'name': name,
'fullname': fullname,
'convert': convertor_cb,
'pre': pre_cb,
'post': post_cb
};
};
QWiki.prototype.convertAndSave = function(path, name, source, cb) {
if (typeof cb === 'undefined') cb = function() {};
if (!(name in this.formats)) {
name = 'raw';
}
console.log('converting to ' + name + ' with path ' + path);
var converted = this.formats[name].convert(source);
QCore.prototype.r_mkdir(m_path.dirname('cache/'+path+'.html'), 0777, function() {
fs.writeFile('cache/'+path+'.html', converted, function(err) {
if (err) {
console.log('error writing "cache'+ path + '.html"');
} else {
console.log('wrote "cache' + path + '.html"');
}
cb();
});
});
};
QWiki.prototype.deleteCache = function(wiki_page, cb) {
fs.unlink('cache/'+wiki_page+'.html', cb);
};
QWiki.prototype.createCache = function(wiki_page, source, cb) {
if (typeof cb === 'undefined') cb = function() {};
var format = this.defaults.format;
if (typeof this.wiki_index.pages[wiki_page] !== 'undefined') {
format = this.wiki_index.pages[wiki_page].format;
}
if (!(format in this.formats)) {
format = 'raw';
}
console.log('createCache: caching ' + wiki_page + ' as ' + format);
var converted = this.formats[format].convert(source);
var path = 'cache/' + wiki_page + '.html';
QCore.prototype.r_mkdir(m_path.dirname(path), 0777, function() {
fs.writeFile(path, converted, function(err) {
if (err) {
console.log('createCache: error writing "' + path + '"');
} else {
console.log('createCache: created "' + path + '"');
}
cb(err);
});
});
};
QWiki.prototype.deletePage = function(wiki_page, cb) {
fs.unlink('wiki/'+wiki_page+'.qwk', cb);
};
QWiki.prototype.savePage = function(wiki_page, content, cb) {
var self = this;
var path = 'wiki/' + wiki_page + '.qwk';
QCore.prototype.r_mkdir(m_path.dirname(path), 0777, function() {
console.log('savePage: writing ' + path);
self.deleteCache(wiki_page, function() {
fs.writeFile(path, content, function(err) {
console.log('savePage: wrote ' + path);
cb(err);
});
});
});
};
QWiki.prototype.deleteFile = function(file, cb) {
fs.unlink('wiki/'+file, cb);
};
if (require.main === module) {
var port = 8080;
process.argv.forEach(function (val, index, array) {
var parts = val.split('=');
var key = '';
var value = '';
if (parts[0].substr(0, 2) == '--') {
key = parts[0].substr(2);
value = parts[1];
}
if (key == 'port') {
if (value == '') {
console.log(key + ' needs a value');
} else {
port = Number(value);
}
}
});
var qwiki = new QWiki();
qwiki.addMIMEtype('png', 'image/png');
qwiki.addMIMEtype('jpg', 'image/jpg');
qwiki.addMIMEtype('svg', 'image/svg+xml');
qwiki.addMIMEtype('css', 'text/css');
var m_markdownit = require('markdown-it')({
typographer: true
});
m_markdownit.use(require('markdown-it-anchor'));
m_markdownit.use(require('markdown-it-table-of-contents'), {includeLevel: "2-8"});
m_markdownit.use(require('markdown-it-deflist'));
m_markdownit.use(require('markdown-it-header-sections'));
m_markdownit.use(require('markdown-it-sup'));
qwiki.addFormat('md', 'Markdown', function(source) {
// source is a Buffer, but render seems to need a String
return m_markdownit.render(source.toString());
});
qwiki.setDefault('format', 'md');
qwiki.listen(port);
}
module.exports = QWiki;