add blog example

master
TJ Holowaychuk 2013-11-27 21:40:00 -08:00
parent 9c652118a9
commit 38ce7c1559
8 changed files with 217 additions and 1 deletions

92
examples/blog/index.js Normal file
View File

@ -0,0 +1,92 @@
/**
* Module dependencies.
*/
var render = require('./lib/render');
var logger = require('koa-logger');
var route = require('koa-route');
var views = require('co-views');
var koa = require('../..');
var app = koa();
// "database"
var posts = [];
// middleware
app.use(logger());
// route middleware
app.use(route.get('/', list));
app.use(route.get('/post/new', add));
app.use(route.get('/post/:id', show));
app.use(route.post('/post', create));
// route definitions
/**
* Post listing.
*/
function *list() {
this.body = yield render('list', { posts: posts });
}
/**
* Show creation form.
*/
function *add() {
this.body = yield render('new');
}
/**
* Show post :id.
*/
function *show(id) {
var post = posts[id];
if (!post) this.throw(404, 'invalid post id');
this.body = yield render('show', { post: post });
}
/**
* Create a post.
*/
function *create() {
var post = yield parse(this);
var id = posts.push(post) - 1;
post.created_at = new Date;
post.id = id;
this.redirect('/');
}
// TODO: use a lib...
var qs = require('querystring');
function parse(ctx) {
return function(done){
var buf = '';
var req = ctx.req;
req.setEncoding('utf8');
req.on('data', function(chunk){ buf += chunk });
req.on('end', function(){
try {
done(null, qs.parse(buf));
} catch (err){
err.body = buf;
err.status = 400;
done(err);
}
});
}
}
// listen
app.listen(3000);

View File

@ -0,0 +1,13 @@
/**
* Module dependencies.
*/
var views = require('co-views');
// setup views mapping .html
// to the swig template engine
module.exports = views(__dirname + '/../views', {
map: { html: 'swig' }
});

View File

@ -0,0 +1,9 @@
<html>
<head>
<title>Blog</title>
</head>
<body>
{% for post in posts %}
{% endfor %}
</body>
</html>

View File

@ -0,0 +1,62 @@
<html>
<head>
<title>{% block title %}Blog{% endblock %}</title>
<style>
body {
padding: 80px;
font: 16px Helvetica, Arial;
}
h1 {
font-size: 2em;
}
h2 {
font-size: 1.2em;
}
#posts {
margin: 0;
padding: 0;
}
#posts li {
margin: 40px 0;
padding: 0;
padding-bottom: 20px;
border-bottom: 1px solid #eee;
list-style: none;
}
#posts li:last-child {
border-bottom: none;
}
textarea {
width: 500px;
height: 300px;
}
input[type=text],
textarea {
border: 1px solid #eee;
border-top-color: #ddd;
border-left-color: #ddd;
border-radius: 2px;
padding: 15px;
font-size: .8em;
}
input[type=text] {
width: 500px;
}
</style>
</head>
<body>
<section id="content">
{% block content %}
<p>Missing content!</p>
{% endblock %}
</section>
</body>
</html>

View File

@ -0,0 +1,17 @@
{% extends 'layout.html' %}
{% block title %}Posts{% endblock %}
{% block content %}
<h1>Posts</h1>
<p>You have <strong>{{ posts.length }}</strong> posts!</p>
<p><a href="/post/new">Create a Post</a></p>
<ul id="posts">
{% for post in posts %}
<li>
<h2>{{ post.title }}</h2>
<p><a href="/post/{{ post.id }}">Read post</a></p>
</li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -0,0 +1,13 @@
{% extends 'layout.html' %}
{% block title %}New Post{% endblock %}
{% block content %}
<h1>New Post</h1>
<p>Create a new post.</p>
<form action="/post" method="post">
<p><input type="text" placeholder="Title" name="title"></p>
<p><textarea placeholder="Contents" name="body"></textarea></p>
<p><input type="submit" value="Create"></p>
</form>
{% endblock %}

View File

@ -0,0 +1,8 @@
{% extends 'layout.html' %}
{% block title %}{{ post.title }}{% endblock %}
{% block content %}
<h1>{{ post.title }}</h1>
<p>{{ post.body }}</p>
{% endblock %}

View File

@ -40,7 +40,9 @@
"ejs": "~0.8.4",
"koa-logger": "~1.0.1",
"koa-static": "~1.2.0",
"co-busboy": "git://github.com/cojs/busboy"
"co-busboy": "git://github.com/cojs/busboy",
"koa-route": "~1.0.2",
"swig": "~1.1.0"
},
"engines": {
"node": "> 0.11.4"