Working version of wiki

This commit is contained in:
Tim Caswell 2012-01-18 17:01:17 +01:00
parent 2971151540
commit 5a1b0f85f4
11 changed files with 157 additions and 18 deletions

42
app.js
View File

@ -1,4 +1,40 @@
var Stack = require('stack');
var Express = require('express');
var Routes = require('./routes');
module.exports = Stack.compose(
);
// TODO: Uncomment when we have internet
// var TryCatch = require('./trycatch');
var App = module.exports = Express.createServer();
// Configuration
App.configure(function(){
App.set('views', __dirname + '/views');
App.set('view engine', 'jade');
// This gives us scoped errors with long stack traces
// TODO: Uncomment when we have internet
// App.use(function (req, res, next) {
// TryCatch(next, next);
// });
App.use(Express.bodyParser());
App.use(Express.methodOverride());
App.use(App.router);
App.use(Express.static(__dirname + '/public'));
});
App.configure('development', function(){
App.use(Express.errorHandler({ dumpExceptions: true, showStack: true }));
});
App.configure('production', function(){
App.use(Express.errorHandler());
});
// Routes
App.get('/', Routes.index);
App.get('/:name', Routes.view);
App.get('/:name/edit', Routes.edit);
App.post('/:name', Routes.save);
App.listen(process.env.PORT || 3000);
console.log("Express server listening on port %d in %s mode", App.address().port, App.settings.env);

57
db.js Normal file
View File

@ -0,0 +1,57 @@
var FS = require('fs');
var Path = require('path');
var Markdown = require('markdown').markdown;
// This function is used to map wiki page names to files
// on the real filesystem.
function pathFromName(name) {
return Path.join(__dirname, "pages", name + ".markdown");
}
// Load a file from disk and parse out the title and generate the HTML
exports.loadPage = function (name, callback) {
// Attempt to load the file from disk
var path = pathFromName(name);
FS.readFile(path, 'utf8', function (err, markdown) {
var exists = true;
if (err) {
// If it's not there, generate a placeholder body
if (err.code === "ENOENT") {
markdown = "# " + name.replace(/_/g, " ") + "\n\n" +
"This page does not exist yet. Be the first to write it.";
exists = false;
} else {
// Forward all other errors on
return callback(err);
}
}
// Parse the markdown extracting the first header as the title
// and then render as an HTML string
var tree = Markdown.parse(markdown);
var title = name;
for (var i = 1, l = tree.length; i < l; i++) {
if (tree[i] && tree[i][0] === "header") {
title = tree[i][2];
tree.splice(i, 1);
break;
}
}
var html = Markdown.toHTML(tree);
// Send back the page as an object
callback(null, {
name: name,
title: title,
exists: exists,
markdown: markdown,
html: html,
});
});
};
// Saving is simple. Just put the markdown in the file
exports.savePage = function (name, value, callback) {
var path = pathFromName(name);
FS.writeFile(path, value, callback);
};

View File

View File

@ -1,8 +1,10 @@
{
"name": "wiki-contest",
"version": "0.0.0",
"author": "Tim Caswell <tim@c9.io>",
"private": true,
"dependencies": {
"express": "2.5.5",
"jade": ">= 0.0.1",
"markdown": "~0.3.1"
}
}
}

View File

@ -0,0 +1,5 @@
# Home Page
This is the homepage of the wiki.
Cool stuff here.

View File

@ -0,0 +1,8 @@
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
color: #00B7FF;
}

31
routes/index.js Normal file
View File

@ -0,0 +1,31 @@
// Load our model abstraction so we can load and save pages in the wiki.
var DB = require('../db');
// When the wiki is initially loaded, simply redirect to the `home` page.
exports.index = function(req, res) {
res.redirect("/home");
};
// Load a page from the database and render as html
exports.view = function (req, res, next) {
DB.loadPage(req.params.name, function (err, page) {
if (err) return next(err);
res.render('view', page);
});
};
// Load a page from the database and render edit form
exports.edit = function (req, res, next) {
DB.loadPage(req.params.name, function (err, page) {
if (err) return next(err);
res.render('edit', page);
});
};
// Save changes to a page and redirect to view page
exports.save = function (req, res, next) {
DB.savePage(req.params.name, req.body.markdown, function (err) {
if (err) return next(err)
res.redirect("/" + req.params.name);
});
}

View File

@ -1,13 +0,0 @@
var Http = require('http');
var Stack = require('stack');
var Creationix = require('creationix');
var App = require('./app');
var PORT = process.env.PORT || 8080;
Http.createServer(Stack(
Creationix.log(),
App
)).listen(PORT);
console.log("Server listening on http://localhost:%s/", PORT);

4
views/edit.jade Normal file
View File

@ -0,0 +1,4 @@
h1= title
form(method="post", action="/" + name)
textarea(name="markdown")= markdown
input(type="submit")

6
views/layout.jade Normal file
View File

@ -0,0 +1,6 @@
!!!
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
body!= body

3
views/view.jade Normal file
View File

@ -0,0 +1,3 @@
h1= title
.article!= html
a(href="/" + name + "/edit")= (exists ? "Edit" : "Create") + " this Page"