kettek2/acts/default.js

185 lines
6.4 KiB
JavaScript

var fs = require('fs');
module.exports = function(qwiki) {
qwiki.rule('', '@@CONTENT@@', function(req, res, instance, next) {
if (req.area == '/' || req.area == '') {
qwiki.rules['updates']['@@CONTENT@@'](req, res, instance, next);
return;
} else {
for (var listing in qwiki.listings) {
if (req.area.substring(1, listing.length+1) == listing) {
req.listing = listing;
qwiki.rules['listing']['@@CONTENT@@'](req, res, instance, next);
return;
}
}
}
// instance.pos, instance.offset, instance.indices
var cache_path = 'cache/'+req.area+'.html';
res.write('<div class="content_row" id="bot">');
res.write('<div class="right">');
qwiki.readFile(res, cache_path, function(type, err) {
if (type == 'FNF') {
// cache does not exist - is there a wiki source?
var wiki_path = 'wiki/'+req.area+'.qwk';
fs.stat(wiki_path, function(err, stats) {
// TODO: stats.isFile()
if (err && err.code == 'ENOENT') {
// the wiki entry does not exist
res.write(req.area + ' does not exist yet');
res.write('</div></div>');
next();
} else if (err) {
// error while statting wiki entry
res.write(req.area + ': ' + err.code);
res.write('</div></div>');
next();
} else {
// wiki entry exists!
fs.readFile(wiki_path, function(err, data) {
if (err) {
res.write(req.area + ': ' + err.code);
res.write('</div></div>');
next();
} else {
qwiki.convertAndSave(req.area, (req.area in qwiki.wiki_index.pages ? qwiki.wiki_index.pages[req.area].format : qwiki.getDefault('format')), data, function() {
qwiki.readFile(res, wiki_path, function(type, err) {
if (type == 'FNF') {
res.write('error while creating cache');
res.write('</div></div>');
next();
} else if (err) {
res.write(req.area + ': ' + err.code);
res.write('</div></div>');
next();
} else {
res.write('</div></div>');
next();
}
});
});
}
});
}
});
} else if (err) {
res.write(req.area + ': ' + err.code);
res.write('</div></div>');
next();
} else {
res.write('</div></div>');
next();
}
});
});
qwiki.rule('', '@@TITLE@@', function(req, res, instance, next) {
res.write('qwiki ' + req.area);
next();
});
qwiki.rule('', '@@PAGE@@', function(req, res, instance, next) {
res.write(req.area);
next();
});
qwiki.rule('', '@@CRUMBS@@', function(req, res, instance, next) {
var parts = req.area.split('/');
var path = '';
parts[0] = '>';
for (var i = 0; i < parts.length; i++) {
path += (i == 0 ? '/' : parts[i]);
res.write('<li><a href="'+path+'">'+parts[i]+'</a></li>');
path += (i == 0 ? '' : '/');
}
next();
});
qwiki.rule('', '@@FOOTER@@', function(req, res, instance, next) {
res.write('<a href="http://kettek.net/qwiki">qwiki</a> Copyright 2015 <a href="http://kettek.net">kts of kettek</a>');
next();
});
qwiki.rule('', '@@QAT@@', function(req, res, instance, next) {
var d = new Date;
d.setHours(0, 0, 0, 0, 0);
res.write(qwiki.qats[d % (qwiki.qats.length-1)].render);
next();
});
qwiki.act('', function(req, res) {
var ext = qwiki.getExt(req.area);
var mimetype = qwiki.getMIMEtype(qwiki.getExt(req.area));
if (mimetype == '') mimetype = 'application/octet-stream';
if (ext !== '') { // write file on disk directly
var path = 'wiki/'+req.area;
fs.stat(path, function(err, stat) {
if (err == null) {
// TODO: etags should actually be based on binary data(CRC32, etc.), not last modified
// TODO: files should not be stat()`d each call, but should be cached and updated when the file updates (how? browser-based upload interface?)
var mtime = stat.mtime.getTime();
if (!(path in qwiki.etags) || qwiki.etags[path] != mtime) {
qwiki.etags[path] = mtime;
}
res.setHeader("Access-Control-Allow-Origin", "*");
//res.header("Access-Control-Allow-Credentials", "true");
res.setHeader("Access-Control-Allow-Headers", "Origin,Content-Type, Authorization, x-id, Content-Length, X-Requested-With");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
if ('if-none-match' in req.headers && req.headers['if-none-match'] == qwiki.etags[path]) {
res.writeHead(304, "Not Modified");
res.end();
} else {
res.writeHead(200, "OK", {
"Content-Type": mimetype,
"Content-Length": stat.size,
"ETag": mtime
});
var rs = fs.createReadStream(path);
rs.on('data', function(chunk) {
res.write(chunk);
});
rs.on('end', function() {
res.end();
});
}
} else if (err.code == 'ENOENT') {
res.writeHead(404);
res.end();
} else {
console.log(err);
res.write(err.message);
res.end();
}
});
} else {
var path = 'wiki/'+req.area+'.qwk';
fs.stat(path, function(err, stat) {
if (err == null) {
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('', '', req, res);
} else {
var path = 'wiki/'+req.area+'/index.html';
fs.stat(path, function(err, stat) {
if (err == null) {
if (req.url[req.url.length-1] !== '/') {
res.writeHead(302, {
'Location': req.url+'/'
});
res.end();
} else {
var rstream = fs.createReadStream(path);
rstream.on('error', function(err) {
res.writeHead(500);
res.end();
});
res.statusCode = 200;
rstream.pipe(res);
}
} else {
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('', '', req, res);
}
});
}
});
}
});
};