Changed QWiki to now load acts from the acts directory. At the moment, there is no 'hotswapping' of acts, but this should be much more manageable.

master
kts of kettek 2016-01-21 16:22:57 -08:00
parent aed7fdfb66
commit 312197cd41
10 changed files with 379 additions and 346 deletions

129
acts/default.js 100644
View File

@ -0,0 +1,129 @@
var fs = require('fs');
module.exports = function(qwiki) {
qwiki.rule('', '@@CONTENT@@', function(req, res, instance, next) {
var area = req.url;
if (area == '') {
area = 'front';
}
// instance.pos, instance.offset, instance.indices
var cache_path = 'cache/'+area+'.html';
qwiki.readFile(res, cache_path, function(type, err) {
if (type == 'FNF') {
// cache does not exist - is there a wiki source?
var wiki_path = 'wiki/'+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(area + ' does not exist yet');
next();
} else if (err) {
// error while statting wiki entry
res.write(area + ': ' + err.code);
next();
} else {
// wiki entry exists!
fs.readFile(wiki_path, function(err, data) {
if (err) {
res.write(area + ': ' + err.code);
next();
} else {
qwiki.convertAndSave(area, (req.url in qwiki.wiki_index.pages ? qwiki.wiki_index.pages[req.url].format : qwiki.getDefault('format')), data, function() {
readFile(res, wiki_path, function(type, err) {
if (type == 'FNF') {
res.write('error while creating cache');
next();
} else if (err) {
res.write(area + ': ' + err.code);
next();
} else {
next();
}
});
});
}
});
}
});
} else if (err) {
res.write(area + ': ' + err.code);
next();
} else {
next();
}
});
});
qwiki.rule('', '@@TITLE@@', function(req, res, instance, next) {
res.write('qwiki ' + req.url);
next();
});
qwiki.rule('', '@@PAGE@@', function(req, res, instance, next) {
res.write(req.url);
next();
});
qwiki.rule('', '@@CONTROLS@@', function(req, res, instance, next) {
res.write('<li><a href="'+req.url+'/edit"><img src="/edit.png">Edit</a></li><li><a href="'+req.url+'/new"><img src="/new.png">New Page</a></li>');
next();
});
qwiki.rule('', '@@CRUMBS@@', function(req, res, instance, next) {
var parts = req.url.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.act('', function(req, res) {
var mimetype = qwiki.getMIMEtype(qwiki.getExt(req.url));
if (mimetype != '') { // write file on disk directly
var path = 'wiki/'+req.url;
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;
}
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);
res.end();
}
});
} else { // no mimetype/ext, it must be a wiki entry
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('', '', req, res);
}
});
};

27
acts/delete.js 100644
View File

@ -0,0 +1,27 @@
module.exports = function(qwiki) {
// **** DELETE
qwiki.rule('delete', '@@CONTENT@@', function(req, res, instance, next) {
res.write('<form action="" method="POST"> Deleting this page will also delete all page revisions! Are you sure you wish to do this?<div class="prompt"><input type="submit" name="submit" value="Yes"><input type="submit" name="submit" value="No"></div></form>');
next()
});
qwiki.act('delete', function(req, res) {
var area = (req.url == '' ? 'front' : req.url.substr(1));
// handle POST
if ('submit' in req.post) {
if (req.post['submit'] == 'Yes') {
qwiki.deletePage(area, function() {
qwiki.deleteCache(area, function() {
console.log('redirecting to '+req.url);
res.writeHead(302, {'Location': req.url});
res.end();
});
});
return;
} else {
res.writeHead(302, {'Location': req.url+'/edit'});
res.end();
}
}
qwiki.parsePage('delete', 'edit', req, res);
});
}

97
acts/edit.js 100644
View File

@ -0,0 +1,97 @@
var fs = require('fs');
module.exports = function(qwiki) {
qwiki.rule('edit', '@@CONTENT@@', function(req, res, instance, next) {
var area = (req.url == '' ? 'front' : req.url.substr(1));
var path = 'wiki/'+area+'.qwk';
res.write('<form action="" method="POST"><div class="edit"><div><label for="page"><span>This is the page name that corresponds to the wiki URL, e.g., my_page => kettek.net/qwiki/my_page</span>Page</label> <input type="text" name="page" value="'+area+'"></div>');
res.write('<div><label for="format"><span>This is the data format of content source, such as HTML or raw.</span>Format</label> <select name="format">');
for (var format in qwiki.formats) {
var page_format = (typeof qwiki.wiki_index.pages[area] !== 'undefined' ? qwiki.wiki_index.pages[area].format : qwiki.getDefault('format'));
res.write('<option ' + (qwiki.formats[format].name == page_format ? 'selected ' : '') + 'value="'+qwiki.formats[format].name+'">'+qwiki.formats[format].fullname+'</option>');
}
res.write('</select></div>');
res.write('</div><div id="edit_content"><label for="content">Content<span>This is the content of the wiki page</span></label> <textarea name="content">');
qwiki.readFile(res, path, function(type, err) {
if (type == 'FNF') {
} else if (err) {
res.write(err);
}
res.write('</textarea></div><div class="prompt"><input type="submit" name="submit" value="cancel"><input type="submit" name="submit" value="save"></div></form>');
next();
});
});
qwiki.rule('edit', '@@CONTROLS@@', function(req, res, instance, next) {
res.write('<li><a href="'+(req.url == '' ? '/' : req.url)+'"><img src="/view.png">View</a></li><li><a href="'+req.url+'/revisions"><img src="/revisions.png">Revisions</a></li><li><a href="'+req.url+'/delete"><img src="/delete.png">Delete</a></li>');
next();
});
qwiki.act('edit', function(req, res) {
var area = (req.url == '' ? 'front' : req.url.substr(1));
// handle POST
if ('submit' in req.post && req.post['submit'] == 'save') {
var old_area = area;
if ('page' in req.post) {
area = req.post['page'];
}
if (typeof qwiki.wiki_index.pages[area] == 'undefined') {
qwiki.wiki_index.pages[area] = {
format: qwiki.getDefault('format')
};
}
// get our format
if ('format' in req.post) {
qwiki.wiki_index.pages[area].format = req.post['format'];
}
//
console.log(old_area + ' vs ' + area);
if (old_area != area) {
fs.rename('wiki/'+old_area+'.qwk', 'wiki/'+area+'.qwk', function() {
qwiki.deleteCache(old_area, function() {
if ('content' in req.post) {
qwiki.savePage(area, req.post['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
qwiki.createCache(area, req.post['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
res.writeHead(302, {'Location': '/'+area+'/edit'});
res.end();
}
});
}
});
}
});
});
} else {
if ('content' in req.post) {
qwiki.savePage(area, req.post['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
qwiki.createCache(area, req.post['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
res.writeHead(302, {'Location': '/'+area+'/edit'});
res.end();
}
});
}
});
}
}
return;
}
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('edit', '', req, res);
});
};

24
acts/index.js 100644
View File

@ -0,0 +1,24 @@
var fs = require('fs');
module.exports = function(qwiki) {
qwiki.rule('index', '@@CONTENT@@', function(req, res, instance, next) {
var path = 'wiki/'+req.url;
console.log('reading path' + path);
fs.readdir(path, function(err, files) {
for (var file in files) {
if (getExt(files[file]) == 'qwk') {
name = files[file].slice(0, -4);
res.write('<li><a href="'+req.url+'/'+name+'">'+name+'</a></li>');
} else {
res.write('<li><a href="'+req.url+'/'+files[file]+'">'+files[file]+'</a></li>');
}
}
next();
});
});
qwiki.act('index', function(req, res) {
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('index', '', req, res);
});
};

28
acts/new.js 100644
View File

@ -0,0 +1,28 @@
module.exports = function(qwiki) {
qwiki.rule('new', '@@CONTENT@@', function(req, res, instance, next) {
var area = req.url;
if (area == '') {
area = 'new_page';
} else {
area = req.url.substr(1) + '/new_page';
}
var path = 'wiki/'+req.url+'.qwk';
res.write('<form action="" method="POST"><div class="edit"><div><label for="page"><span>This is the page name that corresponds to the wiki URL, e.g., my_page => kettek.net/qwiki/my_page</span>Page</label> <input type="text" name="page" value="'+area+'"></div>');
res.write('</div><div class="prompt"><input type="submit" name="submit" value="edit"></div></form>');
next();
});
qwiki.act('new', function(req, res) {
// handle POST
if ('submit' in req.post && req.post['submit'] == 'edit') {
if ('page' in req.post) {
res.writeHead(302, {'Location': '/'+req.post['page']+'/edit'});
res.end();
return;
}
}
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('new', 'edit', req, res);
});
};

12
acts/revisions.js 100644
View File

@ -0,0 +1,12 @@
module.exports = function(qwiki) {
// **** REVISIONS
qwiki.rule('revisions', '@@CONTENT@@', function(req, res, instance, next) {
var path = 'wiki/'+req.url+'.qwk';
res.write('revisions for ' + req.url.substr(1));
next()
});
qwiki.act('revisions', function(req, res) {
console.log("revisions action");
qwiki.parsePage('revisions', 'edit', req, res);
});
};

17
acts/search.js 100644
View File

@ -0,0 +1,17 @@
module.exports = function(qwiki) {
// **** SEARCH
qwiki.rule('search', '@@CONTENT@@', function(req, res, instance, next) {
if ('submit' in req.post) {
if ('search' in req.post) {
res.write('Results for: ' + req.post['search']);
}
}
next();
});
qwiki.act('search', function(req, res) {
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('search', '', req, res);
});
};

8
acts/upload.js 100644
View File

@ -0,0 +1,8 @@
module.exports = function(qwiki) {
qwiki.act('upload', function(req, res) {
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('upload', '', req, res);
});
};

17
acts/view.js 100644
View File

@ -0,0 +1,17 @@
module.exports = function(qwiki) {
// **** VIEW
qwiki.act('view', function(req, res) {
if (req.url == '') {
req.url = 'index';
}
var path = 'wiki/'+req.url+'.qwk';
qwiki.readFile(res, path, function(type, err) {
if (type == 'FNF') {
} else if (err) {
res.write(err);
}
res.end();
});
});
};

366
index.js
View File

@ -90,10 +90,26 @@ var QCore = function() {
}
});
};
// TODO: loadActs should allow for dynamic updates by using fs.watch and clearing the require cache
this.loadActs = function(cb) {
var self = this;
fs.readdir('acts', function(err, files) {
if (err) throw err;
for (var i = 0; i < files.length; i++) {
var ext = self.getExt(files[i]);
if (ext == 'js') {
console.log('Loading act: ' + files[i]);
require('./acts/'+files[i])(self);
}
}
(typeof cb !== 'undefined' ? cb() : '');
});
};
fs.watch('index.html', this.loadIndex);
};
QCore.prototype.defaults = {};
QCore.prototype.listen = function(port) {
this.loadActs();
this.loadIndex();
this.loadWikiIndex();
try {
@ -121,6 +137,7 @@ QCore.prototype.getMIMEtype = function(ext) {
return '';
};
QCore.prototype.loadWikiIndex = function() {
var self = this;
try {
this.wiki_index = JSON.parse(fs.readFileSync('index.json'));
} catch (e) {
@ -138,7 +155,7 @@ QCore.prototype.loadWikiIndex = function() {
wiki_index.pages[wiki_file] = { dir: true };
}
} else {
if (getExt(file) == 'qwk') {
if (self.getExt(file) == 'qwk') {
if (wiki_file in wiki_index.pages) {
} else {
var name = wiki_file.slice(0, -4);
@ -342,350 +359,6 @@ qwiki.addFormat('md', 'Markdown', function(source) {
qwiki.setDefault('format', 'md');
// **** DEFAULT
qwiki.rule('', '@@CONTENT@@', function(req, res, instance, next) {
var area = req.url;
if (area == '') {
area = 'front';
}
// instance.pos, instance.offset, instance.indices
var cache_path = 'cache/'+area+'.html';
readFile(res, cache_path, function(type, err) {
if (type == 'FNF') {
// cache does not exist - is there a wiki source?
var wiki_path = 'wiki/'+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(area + ' does not exist yet');
next();
} else if (err) {
// error while statting wiki entry
res.write(area + ': ' + err.code);
next();
} else {
// wiki entry exists!
fs.readFile(wiki_path, function(err, data) {
if (err) {
res.write(area + ': ' + err.code);
next();
} else {
qwiki.convertAndSave(area, (req.url in qwiki.wiki_index.pages ? qwiki.wiki_index.pages[req.url].format : qwiki.getDefault('format')), data, function() {
readFile(res, wiki_path, function(type, err) {
if (type == 'FNF') {
res.write('error while creating cache');
next();
} else if (err) {
res.write(area + ': ' + err.code);
next();
} else {
next();
}
});
});
}
});
}
});
} else if (err) {
res.write(area + ': ' + err.code);
next();
} else {
next();
}
});
});
qwiki.rule('', '@@TITLE@@', function(req, res, instance, next) {
res.write('qwiki ' + req.url);
next();
});
qwiki.rule('', '@@PAGE@@', function(req, res, instance, next) {
res.write(req.url);
next();
});
qwiki.rule('', '@@CONTROLS@@', function(req, res, instance, next) {
res.write('<li><a href="'+req.url+'/edit"><img src="/edit.png">Edit</a></li><li><a href="'+req.url+'/new"><img src="/new.png">New Page</a></li>');
next();
});
qwiki.rule('', '@@CRUMBS@@', function(req, res, instance, next) {
var parts = req.url.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.act('', function(req, res) {
var mimetype = qwiki.getMIMEtype(getExt(req.url));
if (mimetype != '') { // write file on disk directly
var path = 'wiki/'+req.url;
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;
}
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);
res.end();
}
});
} else { // no mimetype/ext, it must be a wiki entry
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('', '', req, res);
}
});
// **** INDEX
qwiki.rule('index', '@@CONTENT@@', function(req, res, instance, next) {
var path = 'wiki/'+req.url;
console.log('reading path' + path);
fs.readdir(path, function(err, files) {
for (var file in files) {
if (getExt(files[file]) == 'qwk') {
name = files[file].slice(0, -4);
res.write('<li><a href="'+req.url+'/'+name+'">'+name+'</a></li>');
} else {
res.write('<li><a href="'+req.url+'/'+files[file]+'">'+files[file]+'</a></li>');
}
}
next();
});
});
qwiki.act('index', function(req, res) {
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('index', '', req, res);
});
// **** UPLOAD
qwiki.act('upload', function(req, res) {
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('upload', '', req, res);
});
// **** VIEW
qwiki.act('view', function(req, res) {
if (req.url == '') {
req.url = 'index';
}
var path = 'wiki/'+req.url+'.qwk';
readFile(res, path, function(type, err) {
if (type == 'FNF') {
} else if (err) {
res.write(err);
}
res.end();
});
});
// **** NEW
qwiki.rule('new', '@@CONTENT@@', function(req, res, instance, next) {
var area = req.url;
if (area == '') {
area = 'new_page';
} else {
area = req.url.substr(1) + '/new_page';
}
var path = 'wiki/'+req.url+'.qwk';
res.write('<form action="" method="POST"><div class="edit"><div><label for="page"><span>This is the page name that corresponds to the wiki URL, e.g., my_page => kettek.net/qwiki/my_page</span>Page</label> <input type="text" name="page" value="'+area+'"></div>');
res.write('</div><div class="prompt"><input type="submit" name="submit" value="edit"></div></form>');
next();
});
qwiki.act('new', function(req, res) {
// handle POST
if ('submit' in req.post && req.post['submit'] == 'edit') {
if ('page' in req.post) {
res.writeHead(302, {'Location': '/'+req.post['page']+'/edit'});
res.end();
return;
}
}
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('new', 'edit', req, res);
});
// **** EDIT
qwiki.rule('edit', '@@CONTENT@@', function(req, res, instance, next) {
var area = (req.url == '' ? 'front' : req.url.substr(1));
var path = 'wiki/'+area+'.qwk';
res.write('<form action="" method="POST"><div class="edit"><div><label for="page"><span>This is the page name that corresponds to the wiki URL, e.g., my_page => kettek.net/qwiki/my_page</span>Page</label> <input type="text" name="page" value="'+area+'"></div>');
res.write('<div><label for="format"><span>This is the data format of content source, such as HTML or raw.</span>Format</label> <select name="format">');
for (var format in qwiki.formats) {
var page_format = (typeof qwiki.wiki_index.pages[area] !== 'undefined' ? qwiki.wiki_index.pages[area].format : qwiki.getDefault('format'));
res.write('<option ' + (qwiki.formats[format].name == page_format ? 'selected ' : '') + 'value="'+qwiki.formats[format].name+'">'+qwiki.formats[format].fullname+'</option>');
}
res.write('</select></div>');
res.write('</div><div id="edit_content"><label for="content">Content<span>This is the content of the wiki page</span></label> <textarea name="content">');
readFile(res, path, function(type, err) {
if (type == 'FNF') {
} else if (err) {
res.write(err);
}
res.write('</textarea></div><div class="prompt"><input type="submit" name="submit" value="cancel"><input type="submit" name="submit" value="save"></div></form>');
next();
});
});
qwiki.rule('edit', '@@CONTROLS@@', function(req, res, instance, next) {
res.write('<li><a href="'+(req.url == '' ? '/' : req.url)+'"><img src="/view.png">View</a></li><li><a href="'+req.url+'/revisions"><img src="/revisions.png">Revisions</a></li><li><a href="'+req.url+'/delete"><img src="/delete.png">Delete</a></li>');
next();
});
qwiki.act('edit', function(req, res) {
var area = (req.url == '' ? 'front' : req.url.substr(1));
// handle POST
if ('submit' in req.post && req.post['submit'] == 'save') {
var old_area = area;
if ('page' in req.post) {
area = req.post['page'];
}
if (typeof qwiki.wiki_index.pages[area] == 'undefined') {
qwiki.wiki_index.pages[area] = {
format: qwiki.getDefault('format')
};
}
// get our format
if ('format' in req.post) {
qwiki.wiki_index.pages[area].format = req.post['format'];
}
//
console.log(old_area + ' vs ' + area);
if (old_area != area) {
fs.rename('wiki/'+old_area+'.qwk', 'wiki/'+area+'.qwk', function() {
qwiki.deleteCache(old_area, function() {
if ('content' in req.post) {
qwiki.savePage(area, req.post['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
qwiki.createCache(area, req.post['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
res.writeHead(302, {'Location': '/'+area+'/edit'});
res.end();
}
});
}
});
}
});
});
} else {
if ('content' in req.post) {
qwiki.savePage(area, req.post['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
qwiki.createCache(area, req.post['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
res.writeHead(302, {'Location': '/'+area+'/edit'});
res.end();
}
});
}
});
}
}
return;
}
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('edit', '', req, res);
});
// **** DELETE
qwiki.rule('delete', '@@CONTENT@@', function(req, res, instance, next) {
res.write('<form action="" method="POST"> Deleting this page will also delete all page revisions! Are you sure you wish to do this?<div class="prompt"><input type="submit" name="submit" value="Yes"><input type="submit" name="submit" value="No"></div></form>');
next()
});
qwiki.act('delete', function(req, res) {
var area = (req.url == '' ? 'front' : req.url.substr(1));
// handle POST
if ('submit' in req.post) {
if (req.post['submit'] == 'Yes') {
qwiki.deletePage(area, function() {
qwiki.deleteCache(area, function() {
console.log('redirecting to '+req.url);
res.writeHead(302, {'Location': req.url});
res.end();
});
});
return;
} else {
res.writeHead(302, {'Location': req.url+'/edit'});
res.end();
}
}
qwiki.parsePage('delete', 'edit', req, res);
});
// **** REVISIONS
qwiki.rule('revisions', '@@CONTENT@@', function(req, res, instance, next) {
var path = 'wiki/'+req.url+'.qwk';
res.write('revisions for ' + req.url.substr(1));
next()
});
qwiki.act('revisions', function(req, res) {
console.log("revisions action");
qwiki.parsePage('revisions', 'edit', req, res);
});
// **** SEARCH
qwiki.rule('search', '@@CONTENT@@', function(req, res, instance, next) {
if ('submit' in req.post) {
if ('search' in req.post) {
res.write('Results for: ' + req.post['search']);
}
}
next();
});
qwiki.act('search', function(req, res) {
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('search', '', req, res);
});
var readFile = function(stream, path, cb) {
fs.exists(path, function(exists) {
if (exists) {
@ -704,6 +377,7 @@ var readFile = function(stream, path, cb) {
}
});
};
QCore.prototype.readFile = readFile;
var readFiles = function(dir, callback) {
fs.readdir(dir, function(err, files) {
@ -721,7 +395,7 @@ var readFiles = function(dir, callback) {
});
};
var getExt = function(file) {
QCore.prototype.getExt = function(file) {
var last = file.lastIndexOf(".");
var ext = file.substr(last+1);
return ext;