Skip to content

Instantly share code, notes, and snippets.

@rjungemann
Created March 11, 2011 18:59
Show Gist options
  • Save rjungemann/866377 to your computer and use it in GitHub Desktop.
Save rjungemann/866377 to your computer and use it in GitHub Desktop.
Work-in-progress RESTful wiki using Node + Connect + CoffeeScript
require.paths.unshift 'vendor/connect/lib'
require.paths.unshift 'vendor/markdown-js/lib'
connect = require 'connect'
markdown = require 'markdown'
class CoffeeWiki
constructor: ->
# The endpoint for the wiki.
@baseUrl = '/pages'
@softlinkModules = [
(args...) =>
url = if args[0].match /^http(s{0,1}):\/\// || args[0].match /^\//
args[0]
else
"#{@baseUrl}/#{@sluggerize args[0]}"
"<a href=\"#{url}\">#{args[1] || args[0]}</a>"
]
# A default set of pages that are loaded.
@pages = {
welcome: {
title: "Welcome"
rawContents: "Hello world! Check out the [[links]] page."
}
links: {
title: "Links"
rawContents: "Second page. Return to the [[welcome|first page]]."
}
}
# Turn a title into a url-friendly format, which can also be used as a key
# to find the page later.
sluggerize: (string) =>
string.replace(/\W+/g, '_').replace(/\_+/, '_').replace(/^\_|\_$/, '')
# Process wiki-styled links in an extensible way. Currently supports
# internal and external links, but could be extended to support loading
# images or other media using a wiki-styled syntax.
softlink: (string) =>
string.replace /\[\[(.+?)\]\]/g, (m, s) =>
for i in [0..(@softlinkModules.length - 1)]
result = @softlinkModules[i].apply null, s.split /\|/
if result then return result
app: (app) =>
# Retrieve a page by slug
app.get "#{@baseUrl}/:slug", (req, res, next) =>
page = @pages[req.params.slug]
page.contents ?= @softlink page.rawContents
body = JSON.stringify page
res.writeHead 200, {
'Content-Type': 'application/json'
'Content-Length': body.length
}
res.end body
# Create or update a page at a user-specified location represented by a
# slug.
app.put "#{@baseUrl}/:slug", (req, res, next) =>
slug = req.params.slug
@pages[slug] ?= {}
@pages[slug].title = req.body.title
@pages[slug].rawContents = req.body.contents
@pages[slug].contents = @softlink req.body.contents
body = JSON.stringify @pages[slug]
res.writeHead 200, {
'Content-Type': 'application/json'
'Content-Length': body.length
}
res.end body
# Create or update a page. This page's slug is determined by sluggerizing
# the provided title.
app.post @baseUrl, (req, res, next) =>
slug = @sluggerize req.body.title
@pages[slug] ?= {}
@pages[slug].rawContents = req.body.contents
@pages[slug].contents = @softlink req.body.contents
body = JSON.stringify @pages[slug]
res.writeHead 200, {
'Content-Type': 'application/json'
'Content-Length': body.length
}
res.end body
# Delete a page by slug. The page existing at that url is returned.
app.delete "#{@baseUrl}/:slug", (req, res, next) =>
slug = req.params.slug
body = JSON.stringify @pages[slug]
@pages[slug] = null
res.writeHead 200, {
'Content-Type': 'application/json'
'Content-Length': body.length
}
res.end body
# Get a list of pages
app.get @baseUrl, (req, res, next) =>
body = JSON.stringify @pages
res.writeHead 200, {
'Content-Type': 'application/json'
'Content-Length': body.length
}
res.end body
coffeeWiki = new CoffeeWiki
server = connect.createServer(
connect.bodyDecoder()
connect.router coffeeWiki.app
)
server.listen 9292
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment