#
# Little Wiki
# config.ru
#
# Christian Koch <cfkoch@sdf.lonestar.org>
#
# -----
#
# Little Wiki is a simple wiki-ish web application based on Christian
# Neukirchen's own mini-framework, Rum. All of your site's content is written in
# Markdown, save the layout, which is written in HTML/ERB. The directory
# heirarchy of Little Wiki is very similar to that of Sinatra:
#
#   lib/
#     rum.rb
#   public/
#     css/
#     jpg/
#   views/
#     index.md
#     layout.erb
#     posts/
#       index.md
#       20120209.md
#       20120315.md
#
# If a client requests a directory, then the file called "index.md" will be
# served if it exists in that directory, otherwise the server will return 404
# Not Found. All other requests should point directly to the desired view, but
# without the .md extension. For example, to read the March 15 post, request for
# http://example.com/posts/20120315. (This means that any Markdown content must
# be stored in a file with a .md extension.)
#
# Two variables are exposed to layout.erb:
#   @mtime       represents the modification time of the requested view
#   @inner_text  contains the HTML result of the requested Markdown content
#                (just like <%= yield %> in Sinatra)
#
# That's pretty much all there is to it. Little Wiki was designed to be tiny,
# fast, and would require one to SSH into the server in order to make changes.
#
# TODO:
#   * Automatically set the HTML <title> of each page to something meaningful.
#

THIS_DIR   = File.dirname(__FILE__)
VIEWS_DIR  = File.join(THIS_DIR, 'views')
LIB_DIR    = File.join(THIS_DIR, 'lib')
PUBLIC_DIR = File.join(THIS_DIR, 'public')

$LOAD_PATH.unshift LIB_DIR
require 'rubygems'
require 'rum'
require 'erb'
require 'rdiscount'

use Rack::CommonLogger
use Rack::ShowExceptions
use Rack::ShowStatus

# This makes the application aware of public dirs *only once* -- therefore, if
# you add a new public dir then you still need to reboot the server.
public_dirs = Dir.glob("#{PUBLIC_DIR}/*").map { |d| "/" + File.basename(d) }
use Rack::Static, :urls => public_dirs, :root => 'public'

#####

LittleWiki = Rum.new do
  def render(template)
    @inner_text = RDiscount.new(
      File.read(File.join(VIEWS_DIR, "#{template}.md")),
      :smart
    ).to_html

    @mtime = File.mtime(File.join(VIEWS_DIR, "#{template}.md"))

    result = ERB.new(File.read(File.join(VIEWS_DIR, 'layout.erb'))).
      result(binding)
    puts result  
  end

  on get, path(/.*/) do |_, slug|
    begin
      if File.file?(File.join(VIEWS_DIR, slug, "index.md"))
        render "#{slug}/index"
      else
        render slug
      end
    rescue
      res.status = 404
    end
  end
end

run LittleWiki
