6d07aadea2c4

Merge the Hyde rewrite.
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sat, 09 Jan 2010 04:01:49 -0500
parents 0908c069150a (diff) da98105753a1 (current diff)
children cb8b12793ae4
branches/tags (none)
files .be/bugs/269a370f-ff8a-4448-825f-d42246f47ca4/values .be/bugs/5c23392b-09f8-46ce-9989-ab815340d3d9/values .be/bugs/8926af58-a7e8-4d53-b2cc-5a58022c7932/values .be/bugs/afed6983-9e2b-4de2-bba6-3e33d225c018/values .be/bugs/b8a907ca-80d6-4121-9975-904ad97fbe92/values .be/bugs/d25d0d59-99c1-46c8-bc55-f4f0c2ce6dd4/values .be/settings .be/version .hgignore .venv __init__.py blog/__init__.py blog/admin.py blog/models.py blog/urls.py blog/views.py convert-comments.py deploy-template.py manage.py projects/__init__.py projects/admin.py projects/models.py projects/urls.py projects/views.py rss/__init__.py rss/feeds.py rss/urls.py settings.py site-media/scripts/jquery.validate.min.js site-media/scripts/print-links.js site-media/scripts/stevelosh-gallery.js site-media/scripts/validate-comment-form.js site-media/scripts/wmd/images/bg-fill.png site-media/scripts/wmd/images/bg.png site-media/scripts/wmd/images/blockquote.png site-media/scripts/wmd/images/bold.png site-media/scripts/wmd/images/code.png site-media/scripts/wmd/images/h1.png site-media/scripts/wmd/images/hr.png site-media/scripts/wmd/images/img.png site-media/scripts/wmd/images/italic.png site-media/scripts/wmd/images/link.png site-media/scripts/wmd/images/ol.png site-media/scripts/wmd/images/redo.png site-media/scripts/wmd/images/separator.png site-media/scripts/wmd/images/ul.png site-media/scripts/wmd/images/undo.png site-media/scripts/wmd/images/wmd-on.png site-media/scripts/wmd/images/wmd.png site-media/scripts/wmd/showdown.js site-media/scripts/wmd/wmd-base.js site-media/scripts/wmd/wmd-plus.js site-media/scripts/wmd/wmd.js site-media/style/aal.css site-media/style/blog.css site-media/style/blueprint/ie.css site-media/style/blueprint/print.css site-media/style/blueprint/screen.css site-media/style/code.css site-media/style/comments.css site-media/style/gallery.css site-media/style/messengerbag.css site-media/style/photoblog.css site-media/style/print.css site-media/style/projects.css site-media/style/splash.css site-media/style/stevelosh.css site-media/style/thoughts.css templates/404.html templates/base.html templates/blog/base.html templates/blog/entry.html templates/blog/list.html templates/feeds/all_description.html templates/feeds/all_title.html templates/feeds/comments_description.html templates/feeds/comments_title.html templates/flatpages/default.html templates/flatpages/splash.html templates/messengerbag/base.html templates/messengerbag/note_detail.html templates/messengerbag/note_form.html templates/messengerbag/note_list.html templates/projects/base.html templates/projects/list.html templates/projects/project.html urls.py

Changes

--- a/.be/bugs/269a370f-ff8a-4448-825f-d42246f47ca4/values	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-
-
-
-creator=Steve Losh <steve@stevelosh.com>
-
-
-
-
-
-
-severity=minor
-
-
-
-
-
-
-status=open
-
-
-
-
-
-
-summary=Install and use django-tagging.
-
-
-
-
-
-
-time=Fri, 30 Jan 2009 01:31:57 +0000
-
-
-
--- a/.be/bugs/5c23392b-09f8-46ce-9989-ab815340d3d9/values	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-
-
-
-creator=Steve Losh <steve@stevelosh.com>
-
-
-
-
-
-
-severity=minor
-
-
-
-
-
-
-status=open
-
-
-
-
-
-
-summary=Refactor to use Djangos built-in pagination.
-
-
-
-
-
-
-time=Fri, 30 Jan 2009 01:32:30 +0000
-
-
-
--- a/.be/bugs/8926af58-a7e8-4d53-b2cc-5a58022c7932/values	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-
-
-
-creator=Steve Losh <steve@stevelosh.com>
-
-
-
-
-
-
-severity=minor
-
-
-
-
-
-
-status=open
-
-
-
-
-
-
-summary=Refactor to use Django-syncr?
-
-
-
-
-
-
-time=Fri, 30 Jan 2009 01:31:44 +0000
-
-
-
--- a/.be/bugs/afed6983-9e2b-4de2-bba6-3e33d225c018/values	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-
-
-
-creator=Steve Losh <steve@stevelosh.com>
-
-
-
-
-
-
-severity=minor
-
-
-
-
-
-
-status=open
-
-
-
-
-
-
-summary=Refactor to use Django's FreeComments.
-
-
-
-
-
-
-time=Fri, 30 Jan 2009 01:31:27 +0000
-
-
-
--- a/.be/bugs/b8a907ca-80d6-4121-9975-904ad97fbe92/values	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-
-
-
-assigned=Steve Losh <steve@stevelosh.com>
-
-
-
-
-
-
-creator=Steve Losh <steve@stevelosh.com>
-
-
-
-
-
-
-severity=minor
-
-
-
-
-
-
-status=open
-
-
-
-
-
-
-summary=Add support for Tumblr photos.
-
-
-
-
-
-
-time=Fri, 30 Jan 2009 01:30:44 +0000
-
-
-
--- a/.be/bugs/d25d0d59-99c1-46c8-bc55-f4f0c2ce6dd4/values	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-
-
-
-assigned=Steve Losh <steve@stevelosh.com>
-
-
-
-
-
-
-creator=Steve Losh <steve@stevelosh.com>
-
-
-
-
-
-
-severity=minor
-
-
-
-
-
-
-status=open
-
-
-
-
-
-
-summary=Install a test site on the server and add it to the fabfile.
-
-
-
-
-
-
-time=Fri, 30 Jan 2009 01:32:14 +0000
-
-
-
--- a/.be/settings	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-
-
-
-rcs_name=hg
-
-
-
--- a/.be/version	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Bugs Everywhere Tree 1 0
--- a/.hgignore	Sat Jan 09 03:42:18 2010 -0500
+++ b/.hgignore	Sat Jan 09 04:01:49 2010 -0500
@@ -1,18 +1,8 @@
 syntax: glob
-*.pyc
-.DS_Store
-*.log
-*.tmproj
-
-fabfile.py
-*.db
 
-site-media/storage/*
-
-syntax: regexp
-# This is ugly but it works.
-deploy-[^t][^e][^m][^p].*
-deploy\.py
-
-[^p][^l][^a][^t][^e][^s]/messengerbag//messengerbag/.*
-
+.DS_Store
+*.pyc
+*.log
+deploy/
+deploy_tmp/
+backups/
--- a/.venv	Sat Jan 09 03:42:18 2010 -0500
+++ b/.venv	Sat Jan 09 04:01:49 2010 -0500
@@ -1,1 +1,1 @@
-stevelosh
+stevelosh-hyde
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DESIGN.mdown	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,6 @@
+Some notes on the design, mostly for myself.
+
+Images
+======
+
+Full images for posts should be 600 pixels wide (or less).
\ No newline at end of file
--- a/blog/admin.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-from stevelosh.blog.models import Entry, Comment
-from django.contrib import admin
-
-class EntryAdmin(admin.ModelAdmin):
-    fieldsets = [
-        ('Entry', { 'fields': ['title', 'snip', 'body'], }),
-        ('Publishing', { 'fields': ['pub_date', 'published'],
-                         'description': "The entry won't be shown on the site unless the Published box is checked." }),
-        ('Advanced', { 'fields': ['slug',],
-                       'classes': ['collapse'], }),
-    ]
-    list_display = ('title', 'snip', 'pub_date',)
-    search_fields = ('title', 'snip', 'body')
-    list_filter = ('pub_date',)
-    date_hierarchy = 'pub_date'
-    ordering = ('-pub_date',)
-    prepopulated_fields = { 'slug': ('title',) }
-
-class CommentAdmin(admin.ModelAdmin):
-    fields = ('name', 'body', 'submitted', 'entry', 'spam')
-    list_display = ('entry', 'name', 'submitted', 'snip', 'spam')
-    search_fields = ('name', 'body')
-    list_filter = ('name', 'entry', 'spam')
-    date_hierarchy = 'submitted'
-    ordering = ('-submitted',)
-
-
-admin.site.register(Entry, EntryAdmin)
-admin.site.register(Comment, CommentAdmin)
\ No newline at end of file
--- a/blog/models.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-from django.db import models
-import datetime
-
-class Entry(models.Model):
-    title = models.CharField(max_length=140)
-    snip = models.CharField(max_length=140)
-    slug = models.SlugField()
-    pub_date = models.DateTimeField('Date Published', 
-                                    default=datetime.datetime.now)
-    body = models.TextField()
-    published = models.BooleanField(default=False)
-    
-    class Meta:
-        verbose_name = 'entry'
-        verbose_name_plural = 'entries'
-    
-    def get_absolute_url(self):
-        return u'/blog/%d/%02d/%s/' % (self.pub_date.year, self.pub_date.month, self.slug)
-    
-    def __unicode__(self):
-        return u'%s' % (self.title,)
-
-class Comment(models.Model):
-    name = models.CharField('Commenter', blank=False, null=False, 
-                            max_length=40)
-    body = models.TextField('Comment', blank=False, null=False)
-    submitted = models.DateTimeField(default=datetime.datetime.now)
-    entry = models.ForeignKey(Entry)
-    spam = models.BooleanField(default=False)
-    
-    def get_absolute_url(self):
-        return self.entry.get_absolute_url() + "#comment-" + str(self.id)
-    
-    def __unicode__(self):
-        return u'%s on %s' % (self.name, self.entry.title)
-    
-    def snip(self):
-        return self.body[:40] + ('...' if len(self.body) > 40 else '')
-    
--- a/blog/urls.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-from django.conf.urls.defaults import *
-
-urlpatterns = patterns('blog.views',
-    url(r'^$',                              'list',      name='blog-list-newest'),
-    url(r'^page/(\d+)/$',                   'list',      name='blog-list-page'),
-    url(r'^comment/$',                      'comment',   name='blog-post-comment'),
-    url(r'^entry/(\d+)/(\d+)/(\d+)/(.*)/$', 'entry',     name='blog-entry'),
-    url(r'^(\d+)/(\d+)/(\d+)/(.*).html/$',  'old_entry', name='blog-old-entry'),
-)
\ No newline at end of file
--- a/blog/views.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-from stevelosh.blog.models import Entry, Comment
-from markdown import markdown
-from django.shortcuts import get_object_or_404, render_to_response
-from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
-from django.core.urlresolvers import reverse
-from django.core.paginator import Paginator
-from akismet import Akismet
-from stevelosh import deploy
-
-ak = Akismet(deploy.AKISMET_API_KEY, blog_url='http://stevelosh.com/')
-
-def entry(request, year, month, day, slug):
-    entry = get_object_or_404(Entry, slug=slug, pub_date__year=year, 
-                              pub_date__month=month, pub_date__day=day,)
-    comments = entry.comment_set.filter(spam=False).order_by('submitted')
-    
-    return render_to_response('blog/entry.html', 
-                              { 'entry': entry, 'comments': comments })
-
-def old_entry(request, year, month, day, slug):
-    return HttpResponsePermanentRedirect(reverse('blog-entry',
-                                         args=(year, month, day, slug)))
-
-def list(request, page=1):
-    page = int(page)
-    
-    entries = Entry.objects.all().filter(published=True).order_by('-pub_date')
-    p = Paginator(entries, 7, orphans=3).page(page)
-    
-    return render_to_response('blog/list.html', 
-        { 'entries': p.object_list,
-          'older_page': p.next_page_number() if p.has_next() else None,
-          'newer_page': p.previous_page_number() if p.has_previous() else None } )
-
-def comment(request):
-    fields = request.POST
-    entry = Entry.objects.get(pk=fields['entry-id'])
-    
-    if ( fields.has_key('name') and 
-         not fields['name'].strip() == '' and
-         not len(fields['name']) < 2 and
-         fields.has_key('body') and 
-         not fields['body'].strip() == '' and
-         not len(fields['body']) < 3 and
-         not len(fields['body']) > 15000):
-        
-        akismet_data = {}
-        akismet_data['user_ip'] = request.META['REMOTE_ADDR']
-        akismet_data['user_agent'] = request.META['HTTP_USER_AGENT']
-        akismet_data['comment_author'] = fields['name']
-        akismet_data['comment_type'] ='comment'
-        spam = ak.comment_check(fields['body'].encode('ascii', 'ignore'), akismet_data)
-        
-        new_comment = Comment(name=fields['name'], 
-                              body=fields['body'], 
-                              entry=entry,
-                              spam=spam)
-        new_comment.save()
-    
-    return HttpResponseRedirect(reverse('blog-entry',
-                                        args=(entry.pub_date.year, 
-                                              entry.pub_date.month, 
-                                              entry.pub_date.day,
-                                              entry.slug)))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/.htaccess	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,19 @@
+{% if GENERATE_CLEAN_URLS %}
+RewriteEngine on
+RewriteBase {{ node.site.settings.SITE_ROOT }}
+
+# Old URLs
+RewriteRule ^blog/entry/(\d+)/(\d\d)/\d+/(.*)$ /blog/$1/$2/$3/ [R=301,L]
+RewriteRule ^blog/entry/(\d+)/(\d)/\d+/(.*)$ /blog/$1/0$2/$3/ [R=301,L]
+
+{% hyde_listing_page_rewrite_rules %}
+
+# listing pages whose names are the same as their enclosing folder's
+RewriteCond %{REQUEST_FILENAME}/$1.html -f
+RewriteRule ^([^/]*)/$ %{REQUEST_FILENAME}/$1.html
+
+# regular pages
+RewriteCond %{REQUEST_FILENAME}.html -f
+RewriteRule ^.*$ %{REQUEST_FILENAME}.html
+
+{% endif %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/about/about.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,85 @@
+{% extends "_flatpage.html" %}
+
+{% hyde
+    title: "About"
+%}
+
+
+{% block article %}
+
+<a href="http://www.flickr.com/photos/sjl7678/2332680141/"
+   title="074/365 by Steve Losh, on Flickr">
+    <img src="http://farm3.static.flickr.com/2378/2332680141_533362e5db_m.jpg"
+         width="173" height="240" alt="074/365" 
+         class="right"/>
+</a>
+
+I'm Steve. I'm from Rochester, NY. I do a lot of different things. If you want
+to get in touch with me, email me at <steve@stevelosh.com> or find me on
+[Twitter](http://twitter.com/stevelosh) or
+[Flickr](http://flickr.com/photos/sjl7678/).
+
+Music
+-----
+
+I play electric and upright bass. I've played in a metal band in the past, but
+right now my focus is on jazz and blues. I'm taking lessons with a wonderful
+teacher and hope to be skilled enough to play at dances and such in the near
+future.
+
+I DJ at swing and blues dances fairly often. My taste is pretty broad, and
+I'll cater to whatever the floor wants, but I tend to personally enjoy
+slightly down-tempo, small-group music. Let me know if you need a DJ for a
+dance.
+
+Dancing
+-------
+
+I've been swing dancing for a little more than five years. My first love is
+Lindy Hop; I go to classes, workshops and exchanges as often as my schedule
+and budget will allow. I also give lessons; I'm not *the* most skilled dancer
+but I do have teaching experience and I'm relatively cheap.
+
+In the past year or two I've started learning about blues dancing. I'm not
+great at it yet but I'm getting there. I think I might enjoy it even more than
+Lindy. My favorite aspect of dancing in general is connection and blues seems
+to bring that out more than any other dance.
+
+Lately I've also started getting my feet wet in tango. Whether it'll ever
+become as important to me as blues or Lindy remains to be seen.
+
+Photography
+----------
+
+I like photographing people. Other things as well, but especially people.
+They're the most interesting subject to me. I tend to gravitate toward the
+"art" aspects of photography more than the "journalism" aspects, but I can
+appreciate both.
+
+I shoot digital and film (35mm and medium format) depending on my time limits
+and mood. I develop film in my bathroom and print it in a rented darkroom.
+When I print digital I use a lab nearby; I don't have the money for a
+professional printer just yet.
+
+I don't make my living from photography but I do take small jobs.
+
+Programming
+-----------
+
+I graduated from [Rochester Institute of Technology](http://rit.edu/) with a
+degree in Computer Science.
+
+I've done a lot of different things in the field so far. Right now the things
+that are captivating me are artificial intelligence and clean, simple,
+*useful* web applications.
+
+I find programming beautiful. That might sound strange, but there are aspects
+of programming and math that I can't describe any other way.
+
+About the Site
+-----------
+
+If you want to know more about the website itself, check out the [project
+page](/projects/stevelosh-com/).
+
+{% endblock %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2008/02/microsoft-entourage-applescript-frustration.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,44 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Entourage + Applescript = Frustration"
+    snip: "This is ridiculous."
+    created: 2008-02-21 15:25:45
+%}
+
+{% block article %}
+
+I've been working on a project lately to automate the setup of some rules and
+schedules in Microsoft Entourage. This isn't the easiest thing in the world
+because Entourage doesn't really support AppleScript for creating rules or
+schedules (though it does an admirable job in a lot of other areas).
+
+We've resorted to GUI scripting to get the job done. This basically means
+we're telling our script to click button X, wait a bit, put "abc" in text
+field Y, click button Z, etc. This is painful, fragile and slow but it does
+what we need in all but one case.
+
+That case is selecting a folder. The folder list dialog that pops up doesn't
+seem to use any of Apple's UI components which makes GUI scripting it nearly
+impossible. Only "nearly" though, because there's a way to get around it: the
+keyboard. AppleScript can type into a window by sending a series of key codes.
+You can select something from the folder list by typing its name, which means
+that as long as you know the name (we do) you can select it. Almost.
+
+There's one more snag: selection by typing will only ever select the first
+item in the list. This means that if you want to select "Inbox" and both the
+"On My Computer" list and the "youremail@server.com" list are open, you can
+only get the first Inbox. Oh, and good luck predicting which one will show up
+first. It seemed to be different each time I opened the window.
+
+Once again the keyboard comes to our rescue. A simple (and excruciatingly
+ugly) fix is to make sure that the only account listing that's open is the one
+we want. How can we do that? Send an up arrow key code 50 times to move to the
+beginning of the list, then left and down codes 50 times. This collapses the
+entire tree. Then just type the name of the account to select it, send the
+right arrow code to expand the tree, and type the folder name to select it.
+
+It's painful, but it works. If anyone has a better solution please let me know
+so I can rip this monstrosity out of my code and try to forget about it.
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2008/04/shooting-girl-jam.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,202 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Shooting Girl Jam"
+    snip: "I’m finally getting the kind of dancing photos I want."
+    created: 2008-04-29 18:31:16
+%}
+
+
+{% block article %}
+
+<a href="http://www.flickr.com/photos/sjl7678/2450406138/"
+   title="GirlJamSaturday-5383 by Steve Losh, on Flickr">
+    <img src="http://farm4.static.flickr.com/3009/2450406138_473b84b17b_m.jpg"
+         width="240" height="161" alt="GirlJamSaturday-5383"
+         class="left" />
+</a>
+
+This past weekend (April 25-28) was [Northeast Girl Jam][] in Rochester, New
+York. Girl Jam is a swing dancing workshop weekend that focuses on classes for
+the followers. It was a huge success; we had a lot of people attend and
+everyone seemed to have a great time. The dances had a ton of energy and the
+late night parties were wonderful (as always).
+
+I took a bunch of photographs over the course of the weekend, mostly during
+the performances and competitions. Once I posted them I got a bunch of
+questions asking me how I did it, so I figured I'd write here about it in more
+detail. I used different techniques each day so I'll go through them one by
+one.
+
+Friday
+------
+
+My goal for the first two nights was to get images with the dancers sharp
+enough to recognize but with enough blur to convey the feeling of movement and
+energy in the room. I started playing with this technique at the blues parties
+in the past and I think I'm really starting to get the hang of it.
+
+<a href="http://www.flickr.com/photos/sjl7678/2449562969/"
+   title="GirlJamFriday-4873 by Steve Losh, on Flickr">
+    <img src="http://farm3.static.flickr.com/2349/2449562969_68c82066e8_m.jpg"
+         width="161" height="240" alt="GirlJamFriday-4873"
+         class="left" />
+</a>
+
+On Friday I only had one of my flashes with me, so I had to make some
+tradeoffs. I bounced the flash from the ceiling to get more even lighting
+(directional light from a bare flash is usually too harsh), but since the
+ceilings in Tango Cafe are so high it took a lot of power. I wound up shooting
+at ISO 1600 and 3200 for most of the night so that my flash could be on a
+lower power setting and fire faster. Even at that ISO the noise isn't really
+that bad since the photos are exposed well (thanks to the flash). This photo
+was shot at ISO 3200 and I don't think the noise distracts from the image much
+at all.
+
+<a href="http://www.flickr.com/photos/sjl7678/2449565301/"
+   title="GirlJamFriday-4943 by Steve Losh, on Flickr">
+    <img src="http://farm3.static.flickr.com/2186/2449565301_e2491e6b7a_m.jpg"
+         width="240" height="161" alt="GirlJamFriday-4943"
+         class="right" />
+</a>
+
+I was using a wide angle lens (18mm) so that I could get entire bodies into
+the frame. One of the things I love about Lindy Hop is that it really uses the
+entire body which this photo really shows off. Cropping off huge parts of
+people in every single shot makes that much harder to see. I set the aperture
+to about f/4 and that gave me enough depth of field to get most things in
+focus at 18mm. I set the shutter speed depending on the amount of ambient
+light; it varied from 1/30 to 1/4 or so.
+
+<a href="http://www.flickr.com/photos/sjl7678/2450392386/"
+   title="GirlJamFriday-5007 by Steve Losh, on Flickr">
+    <img src="http://farm3.static.flickr.com/2410/2450392386_a61067e07f_m.jpg"
+         width="161" height="240" alt="GirlJamFriday-5007"
+         class="left" />
+</a>
+
+The trick that really made a difference in taking good photos is that once I
+set the exposure I stopped looking at the camera entirely. I didn't review my
+shots as I took them and I didn't even look through the viewfinder to compose.
+Using a wide lens meant that I could just point the camera in the general
+direction of the dancers and still get them. I took this photo at the late
+night and the camera was held against my ribs as I did.
+
+Why did I do that? I can perfectly compose an image but if the dancers aren't
+doing something interesting it's going to be a boring photo. I've been dancing
+long enough that I'm starting to be able to predict when something cool will
+happen in a dance, but that only works if I'm paying complete attention to it.
+Messing with the camera distracts me and I can only get the most obvious
+moments. Ignoring the camera and watching the dancers means I can pick up more
+subtle parts of the dance and capture those (as well as the obvious ones).
+
+Saturday
+--------
+
+On Saturday I brought along two flashes to the dance and had Sergey hold one
+while I held the other (thanks Sergey!). Two flashes means twice as much
+light, which means I can shoot with recycle times twice as fast and have more
+even light coverage.
+
+<a href="http://www.flickr.com/photos/sjl7678/2450405794/"
+   title="GirlJamSaturday-5379 by Steve Losh, on Flickr">
+    <img src="http://farm3.static.flickr.com/2227/2450405794_940545d63d_m.jpg"
+         width="161" height="240" alt="GirlJamSaturday-5379"
+         class="left" />
+</a>
+
+Since I was able to shoot twice as many photos I was able to experiment with
+getting up close. Using a wide angle lens let me get most of the dancers in
+the frame when super close and allowed me to play around with really
+interesting perspectives. This photo is one of my favorites from the weekend.
+Getting really close to Nina means that the distance between her and Carl is
+exaggerated and adds to the sense of tension. Once again, the flashes freeze
+the dancers and the ambient light burns in a bit of blur to add some movement.
+This photo was also shot at ISO 1600 but the noise is definitely not the main
+focus of this picture. As long as you don't underexpose noise is usually not a
+problem in these kind of photos.
+
+<a href="http://www.flickr.com/photos/sjl7678/2450404742/"
+   title="GirlJamSaturday-5349 by Steve Losh, on Flickr">
+    <img src="http://farm3.static.flickr.com/2256/2450404742_3d9a3df777_m.jpg"
+         width="161" height="240" alt="GirlJamSaturday-5349"
+         class="right" />
+</a>
+
+Not only did I try getting up close, I also tried varying my angle more than I
+usually do. I usually brace the camera against my ribs when taking these kinds
+of photos for a few reasons:
+
+* It's a safe height that will get the whole dancer in the frame.
+* My ribs are vertical and so aligning the camera with them means that it's
+  not wildly tilted up or down and I don't accidentally get ceiling- or
+  floor-only photos.
+* It keeps the camera close to my body where it's much less likely to be
+  whacked by a stray limb.
+
+Getting lower and higher gives me different perspectives that can have really
+nifty results. The problem is that it's much harder to know if the subject is
+completely (or even mostly) in the frame when the camera is in an awkward
+position. To get a photo like this I probably shot four or five at strange
+angles that I deleted.
+
+One other fun thing to notice: you can see Sergey holding the flash right to
+the left of her hips. I probably could have cloned out the flare in Photoshop
+but I don't think it really detracts from the image much at all.
+
+Sunday
+-------
+  
+<a href="http://www.flickr.com/photos/sjl7678/2449592347/"
+   title="GirlJamSunday-5647 by Steve Losh, on Flickr">
+    <img src="http://farm4.static.flickr.com/3066/2449592347_6a17602cd9_m.jpg"
+         width="161" height="240" alt="GirlJamSunday-5647"
+         class="left" />
+</a>
+
+On Sunday I shot at a few of the workshops since there wasn't a dance. A
+workshop has a very different feeling than a dance and so I didn't want to try
+the same approach as the other two nights. Instead of using flash and a wide
+lens I switched to a fast normal lens (my 50mm f/1.4). The light coming
+through the windows was bright enough that I was able to shoot at around 1/60
+at f/2 or f/2.8 and ISO 800 or 1600.
+
+Once again the noise isn't much of a problem because the photos are exposed
+well as this picture shows. The shutter speed is just slow enough to get some
+blur at the ends of the limbs but not enough to lose all detail.
+
+<a href="http://www.flickr.com/photos/sjl7678/2449590741/"
+   title="GirlJamSunday-5512 by Steve Losh, on Flickr">
+    <img src="http://farm3.static.flickr.com/2076/2449590741_b47a5ced4c_m.jpg"
+         width="161" height="240" alt="GirlJamSunday-5512"
+         class="right" />
+</a>
+
+Since I was using a normal lens instead of a wide angle I had to mostly
+abandon the idea of getting big group photos and instead try to capture
+individual people as they learned. Using a wide aperture let me isolate the
+people from the sea of arms and legs in the backgrounds and gave the images a
+soft quality that helps reflect the feeling of the afternoon.
+
+I really like the soft-yet-directional light that came from the big stained
+glass windows combined with the overhead lights. Lately I've been using flash
+a lot in my photography and it was fun to get back to using natural light. I'm
+going to try to practice with it more in the near future.
+
+Overall
+-------
+
+Northeast Girl Jam was awesome. I had a great time dancing and photographing
+and got to see a lot of old friends (and meet new ones). If you're sad you
+missed it there's another event in Rochester next month: [Stompology][]. It's
+a weekend of solo jazz and Charleston workshops and awesome swing dances.
+
+If you'd like to see the rest of the photos I took this weekend I posted them
+on [Flickr][]. Feel free to comment here or there; advice/questions/comments
+are always appreciated!
+
+[Flickr]: http://flickr.com/photos/sjl7678/collections/72157604785390431/
+[Stompology]: http://stompology.com/
+[Northeast Girl Jam]: http://jojojackson.com/NEGJ/Home.html
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2008/08/beauty-in-computer-science-recursion.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,180 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Beauty in Computer Science"
+    snip: "Why I love what I do."
+    created: 2008-08-29 15:30:38
+%}
+
+
+{% block article %}
+
+When I went to college, I majored in Computer Science. I haven't really
+written anything about this part of my life yet, so I figured this might be a
+good time to start.
+
+I decided to major in CS when I was in high school. I learned to program on my
+own and enjoyed the challenge of it. I also knew that programming jobs are
+fairly common and pay well enough that I wouldn't have to worrying about
+paying my rent. I wasn't artistic in high school, and CS seemed like a
+logical, sterile field that I felt I could do well in.
+
+During the years I spent at RIT I changed quite a bit. I think the most
+important, or at least the most obvious, change has been my becoming more
+artistic. Between dancing, playing bass and photography I've developed a
+creative side that I never thought I could. Has this led me away from Computer
+Science at all?
+
+No. While I became a programmer for practical reasons, I stayed one for
+entirely different reasons. Computer Science (and math in general) is
+beautiful. It took me years to slowly realize this, but now that I have I see
+that it's more beautiful than any dance, photograph of music I've ever
+encountered. This post is the first in a series of posts that I hope can
+communicate why I find CS beautiful, or at least point in the right direction.
+
+A Quick Primer on "Functions" for Non-Programmers
+---------
+
+I know that most (if not all) of the people that read my website don't
+program. I'm going to try to avoid using extremely technical, computer sciency
+terms in these posts, but there are at least a few basic things that I need to
+explain. The first is what a function is.
+
+Think of a function as a set of instructions. A recipe is a decent example.
+Imagine you have a piece of paper with the following written on it:
+
+1. Heat a frying pan.
+2. Crack two eggs into a bowl.
+3. Mix the eggs.
+4. Pour the mixture into the hot frying pan.
+5. Stir the mixture until it is solid.
+6. Take the mixture out of the pan.
+
+That's the simplest example of a function: a list of instructions that you
+follow in the order you get them. The next idea is a "parameter." That recipe
+only told us how to make food for one person, wouldn't it be nice to know how
+to make enough for two or more? Imagine the paper now says this:
+
+1. Heat a frying pan.
+2. Crack NUMBER_OF_PEOPLE * 2 eggs into a bowl.
+3. Mix the eggs.
+4. Pour the mixture into the hot frying pan.
+5. Stir the mixture until it is solid.
+6. Take the mixture out of the pan.
+
+Now we still have a single piece of paper, but by just substituting in the
+number of people we're cooking for we have instructions for making any amount
+of food. If we have three people, NUMBER_OF_PEOPLE * 2 eggs becomes 3 * 2
+eggs, or 6 eggs.
+
+The last important concept is "calling." Once you have one function, you can
+use it in other functions, like so:
+
+1. Put a plate on the table.
+2. Refer to the other piece of paper and do what it says, for 1 person.
+3. Put the result of that on the plate.
+4. Eat it.
+
+See how we did a few things, then referred to the other piece of paper instead
+of repeating ourselves? This lets you make small tasks and put them together
+to form bigger ones. That's enough of a primer for now; if something's not
+clear please comment and let me know.
+
+What's Recursion?
+---------------
+
+Recursion is a term that means, basically, a function calls (or refers to)
+itself. This concept can be hard to grasp, but once you do it slowly turns
+into something breathtakingly beautiful.
+
+Here's a simple example: imagine you're 10 meters away from a doorway and you
+want to walk out of it. A function that could help you do this might be: "Walk
+11 meters." That's pretty simple.
+
+What if we want to be able to walk out of a doorway that's any number of
+meters ahead of us? We could say: "Walk DISTANCE + 1 meters." This works, but
+requires that you know how many meters away the door is before you even start
+walking. What if we don't?
+
+How about we just do a little at a time and see how it goes? "Walk 2 meters.
+If you're out of the doorway, stop. Otherwise, repeat this function." If the
+doorway is 3 meters in front of us, we'll walk 2, check if we're out (we're
+not), and repeat. We'll walk 2, check if we're out (we are), and stop. This
+function is recursive; it refers back to itself.
+
+Why is it beautiful?
+--------------
+
+The beauty of recursion, for me, is that you can build infinitely large or
+complex tasks or structures using one or two tiny, simple parts. I'll give an
+example of this because I think it's the easiest way for me to show it.
+
+Imagine that you only know three things: how to add 1 to a number, how to
+subtract 1 from a number, and what 0 means. Now imagine that you want to be
+able to add any two (positive) numbers (integers) together. How could you do
+this? Here's a function:
+
+    function add(x, y):
+        if y = 0:
+            return x
+        otherwise:
+            return add( x+1, y-1 )
+
+Don't let the new notation scare you; it's the same kind of function as
+always. In English, it says "This function is named 'add' and needs two
+parameters (x and y). Step one is to see if y is 0. If it is, the result is x.
+If it's not, then the result is whatever you get from performing this function
+with the following parameters: x+1, y-1."
+
+It might not be immediately obvious that this will actually perform the
+addition we're used to, so let's try it. First, let's try adding 1 + 0. In
+that case, we check if y is 0. It is, so the result is x, or 1. So far, so
+good.
+
+Let's try 2 + 1. Is y equal to 0? No, so we need to call add with some new
+parameters. 2+1 is 3, 1-0 is 0, so the result is now whatever we get from
+add(3, 0). We start following the instructions of add. Does y equal 0? Yes, so
+the result is 3, which is what we expect.
+
+One more for good measure: 9 + 2. First we check if y is 0. It's not, so the
+result is then add(9+1, 2-1), or add(10,1). Start over. Is y zero? Nope, so
+the result is now add(11, 0). Start over. Is y zero? Yes, so the result is x,
+or 11.
+
+So What?
+--------
+
+This will work for any x and any y (as long as they're both positive, negative
+numbers make it just a tiny bit more complicated). This might not seem
+impressive, but think about what we've done. We've created something that can
+add any two numbers together. There are an infinite amount of numbers. This
+tiny function that we've made from the simplest of parts can generate more
+results than there are people on this planet. Or atoms in the universe. To me,
+this is amazing. Not "magic trick" amazing or "miracle" amazing but "I can
+understand and create something that can describe more knowledge than the
+whole of humanity couldn't hope to describe in a thousand lifetimes" amazing.
+
+Computer Science (and math in general) is full of this kind of beauty. I've
+tried to find parallels in my other interests; the closest I've found is the
+photograph [Pale Blue Dot][]. It's a photo taken by the Voyager 1 space probe
+showing an immense amount of space with the tiniest blue speck in the middle,
+which is Earth.
+
+When you view the photograph, it's a mostly black field with a little fleck of
+blue pigment. Not terribly complicated or interesting, until you realize that
+that blue fleck is a representation of the planet that billions of people have
+lived and died on. A smidgen of blue ink, in the right context, represents
+every place a human has ever called "home."
+
+Our addition function might not seems nearly as nifty as this, but it actually
+represents more than even this photo ever can. There are a finite number of
+people on Earth, but the addition function can add more numbers that that.
+Even if you count every second in the life of every person that has ever lived
+on our planet, the addition function can create more numbers than that.
+
+This awes me more than any myth, photograph, story, song, legend or dance ever
+has. It's the reason I stayed a Computer Scientist.
+
+[Pale Blue Dot]: http://en.wikipedia.org/wiki/Pale_Blue_Dot
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2008/08/negative-space-dancing.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,103 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Negative Space in Dancing"
+    snip: "It’s not just for artsy kids."
+    created: 2008-08-31 15:33:57
+%}
+
+
+{% block article %}
+
+Last night a few of us from Rochester drove to Buffalo for a swing event.
+There were three classes during the afternoon that were pretty fun. There was
+a dance in the evening which had a great turnout and plenty of energy. As nice
+as all that was, the real highlight of the day/night was the blues party after
+the dance. Matt and I ended up DJ'ing it and it was absolutely awesome. I got
+to meet and dance with a whole bunch of new people that I hope to dance with
+again soon.
+
+One concept I try to use in my blues (and tango) dancing is that of negative
+space. I've found that a lot of blues dancers don't really seem to quite get
+that idea. I'm not saying that it's the "right" way to blues dance but it's
+something that's changed how I dance and I wanted to write something about it
+to share it with anyone interested.
+
+What is negative space?
+-------------------
+
+Negative space is a term used a lot in painting, photography, graphic design,
+etc. It basically means that for a given photo (or painting, whatever) the
+whole frame isn't filled with "things." Two examples of this taken from my
+flickr favorites are [this photo][1] and [this one][2]. In both of these
+images the subject takes up only a small portion of the frame. The expanses of
+even texture and tone add certain qualities to the photos that can't be
+achieved otherwise.
+
+A photographer that takes this to an extreme is Hiroshi Sugimoto, in his
+[Seascape][] series. He uses long exposures and darkroom techniques to produce
+images of nothing but negative space. The sea blends into a seamless texture
+and the sky becomes a single tone. Even though there isn't a physical object
+between the two, the division between them forms a subject of its own.
+
+How does it relate to dancing?
+------------------------
+
+Most of the blues dancers I know come from a Lindy Hop background. Lindy Hop
+is a dance of movement and momentum; that's part of what makes it so much fun.
+When blues dancing I think a lot of Lindy Hoppers never catch on to this idea:
+*you don't need to be moving all of the time*. It's alright to slow down and
+actually stop for one, two, three, four measures. It gives the dance a chance
+to breathe and lets you focus on your connection with your partner without
+movement getting in the way.
+
+"Won't that be boring?" No. Absolutely not. Stopping can provide things that
+you can't really get while moving. It can add tension, release it, and
+completely change the mood of a dance. It really does have a lot in common
+with negative space in art, and it adds a lot to a dance.
+
+Negative space does not mean "empty space," although it's often described like
+that. In the first photo I linked to the wall is indeed blank, but has color
+and texture that can give you plenty to look at. In the second, the expanses
+of white are just that: white. They are not empty; they have a distinct tone:
+white. If they were black, or even a light grey the photo would be entirely
+different.
+
+In dancing, movement is important but not the only thing we think about.
+Posture and body positioning is one example. "Feeling" or "mood" is another,
+more elusive, one. Just because the movement is gone doesn't mean all these
+other things go away automatically; they're still there until you let them go.
+
+Taking it to the extreme like Sugimoto's Seascapes is also emphatically *not*
+boring. In some of the best blues dances I've ever had there were parts where
+we didn't really move for several measures at a time. When this happens, both
+of you create your own negative space through your posture, etc. Neither of
+these spaces are empty.
+
+Where these spaces meet is your connection. Like the horizons in Sugimoto's
+photographs it becomes the main subject. By eliminating motion you're free to
+focus your attention on other aspects of the connection. Sometimes these
+aren't obvious at first. One example Mihai likes to talk about is breathing.
+Another is understanding where your partner's weight is.
+
+By giving yourself time to really feel the connection with your partner you
+have time to examine it much more closely. You can introduce tiny movements
+(like the waves that fleck the surface of the water in Sugimito's seas) that
+interrupt the absolute flatness of the spaces and let you explore the
+interactions between them. Not only does this let you learn about how your
+partner is connected to you in a more in-depth way, it's very, very fun.
+
+I don't have a particularly amazing ending for this post. The main points I
+wanted to get across are these: Negative space in dancing is removing most or
+all of the movement for a longer-than-normal about of time. Negative space is
+not empty space unless you ignore all the other aspects of the dance like
+posture, mood and connection. Negative space can add things to a dance that
+you can't get otherwise.
+
+Try it.
+
+[1]: http://flickr.com/photos/theoperamafia/2790037114/
+[2]: http://flickr.com/photos/jodiseva/2385347094/
+[Seascape]: http://www.sugimotohiroshi.com/seascape.html
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2008/08/on-leading.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,90 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "On Leading"
+    snip: "Some of my thoughts on leading after five years of doing it."
+    created: 2008-08-01 15:28:33
+%}
+
+
+{% block article %}
+
+For those of you that don't know, one of the things I do with my free time is
+dancing. I've been swing dancing (Lindy Hop) for about five years, blues
+dancing for a year or so, and recently started learning tango. All of these
+dances are improvised partner dances and so rely heavily on leading and
+following. People do make routines but at least 95% of it is unrehearsed
+social dancing with partners you might have never met.
+
+As a male I'm usually in the role of leader, though I do try to follow when I
+get the chance. I've learned a lot over the years so I'm going to write a few
+posts about leading, and this is the first. I'm going to use the traditional
+pronouns to make things easier to read, but everything applies to both genders
+in both roles.
+
+Beginning
+-----
+
+When a guy is first taught how to swing dance (or blues, or tango; everything
+I'm saying applies to all three) he's usually taught that his main job is to
+lead. This sounds obvious, but it's a lot for a beginner to take in. He has to
+learn the footwork and ingrain it into his memory so it becomes automatic,
+which takes some time. The next step is learning individual moves: not only
+how to do them himself but also how to lead a follower to do them at the same
+time. It takes coordination and most of all practice.
+
+Leading at this point involves clearly showing the follower where she should
+go and what she should do. "Placing the follower's weight" is a concept that's
+a bit tricky but very useful. If a leader isn't clear in his leading the
+follower won't be able to follow him unless she "cheats" and just does what
+she knows he wants her to do (because she's danced with him before and so
+knows what he's trying to do). This falls apart when the leader dances with a
+new partner. Without leading and following swing dancing just doesn't work, so
+leading clearly is the main role of a beginner guy.
+
+Moving On
+-----
+
+Let me take a second to explain something I see happen very often with leaders
+that take classes and progress nicely in their skill. Once the leader gets the
+basics down pat and starts learning more moves, there seems to be a tendency
+to learn things that let him show off. The followers get to really shine in
+Lindy Hop quite a bit, so it's only natural for the guys to want to measure up
+and look cool themselves. Unfortunately I think this gets in the way of my
+next idea.
+
+I think once a leader reaches a point where he's comfortable with the
+structure of the dance and has a repertoire of moves and vocabulary of
+movements, his role changes. His job is no longer "lead." His role becomes
+*"lead the follower you are dancing with right now."*
+
+Every follower is different. Every single one has a different level of
+experience, a different style, and a different personality (as it relates to
+dancing). If the leader simply leads every dance the same way, those dances
+are not as good as they could be. An "advanced" leader leading a beginner
+follower in a lot of complicated movements she's not capable of following yet
+turns into a complete mess. He goes away from the dance feeling bored or
+frustrated (or worse, arrogant) and she goes away feeling confused,
+discouraged or angry. This is not a good thing.
+
+Paying attention to the follow's level is critical. I'm not saying "only do
+moves that the follower has learned and can easily follow." Pushing the
+follower slightly beyond her comfortable, "automatic" level is wonderful and
+helps her immensely; but going totally over her head and confusing the hell
+out of her just so he can show off (to her or others) is obnoxious. This also
+works in reverse: followers, please challenge your leaders but be mindful of
+their skill.
+
+Experience isn't the only difference between followers. Each follower has her
+own style that won't always fit perfectly with the leader's personal style.
+Adjusting his style to mesh better with hers makes the connection between
+partners so much better, which makes the dance that much more fun. This also
+works both ways. Followers are generally better at "listening" to their
+partner because it's their main job; if a lead makes an effort to really
+listen to the follow and change his leading to incorporate her ideas,
+personality, style and level it makes an enormous difference.
+
+The point I'm trying to make is that "leading" a follower is not just leading.
+It's paying attention to the follower and leading *her*.
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/01/deploying-site-fabric-and-mercurial.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,216 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Deploying with Fabric &amp; Mercurial"
+    snip: "Trimming typing."
+    created: 2009-01-15 20:51:09
+%}
+
+{% block article %}
+
+Earlier tonight I added support for the [Mint][] [Bird Feeder][] plugin to my
+site's [RSS feeds][]. Bird Feeder isn't designed to work with [Django][] so I
+had to change a few things to get it up and running. I mostly followed the
+[instructions on
+Hicks-Wright.net](http://hicks-wright.net/blog/minty-django-feeds/) with a few
+tweaks.
+
+While I was trying to get things running smoothly I had to redeploy the site a
+bunch of times so I could test the changes I made. If I were simply FTP'ing
+the files over each time I wanted to redeploy it would have been a huge pain.
+Fortunately, I have another way to do it that cuts down on my typing.
+
+[Mint]: http://haveamint.com
+[Bird Feeder]: http://haveamint.com/peppermill/pepper/11/bird_feeder/
+[RSS feeds]: /rss/
+[Django]: http://djangoproject.com/
+
+[TOC]
+
+My Basic Deployment Steps
+-------------------------
+
+The code for my site is stored in a Mercurial repository. There are actually
+three copies of the repository that I use:
+
+* One is on my local machine, which I commit to as I make changes.
+* One is on [BitBucket][], which I use to share the code with the public.
+* One is on my host's webserver, and is what actually gets served as the website.
+
+When I'm ready to deploy a new version of the site, I push the changes I've
+made on my local repository to the one on BitBucket, then pull the changes
+from BitBucket down to the server. Using push/pull means I don't have to worry
+about transferring the files myself. Using BitBucket in the middle (instead of
+going right from my local machine to the server) means I don't have to worry
+about serving either repository myself and dealing with port forwarding or
+security issues.
+
+[BitBucket]: http://bitbucket.org
+
+Putting BitBucket in the Middle
+-------------------------------
+
+Using BitBucket as an intermediate repository is actually fairly simple. Here
+are the basic steps I use to get a project up and running like this.
+
+First, create a new repository on BitBucket. Make sure the name is what you
+want. Feel free to make it private if you just want it for this, or public if
+you want to [go open source][].
+
+[go open source]: /blog/entry/2009/1/13/going-open-source/
+
+### Set Up Your Local Machine
+
+Clone this new, empty repository to your local machine. If you already have
+code written you'll need to copy it into this folder after cloning. I don't
+know if there's a way to push a brand-new repository to BitBucket; if you know
+how please tell me.
+
+On your local machine, edit the `.hg/hgrc` file in the repository and change
+the default path to:
+
+	default = ssh://hg@bitbucket.org/username/repositoryname/
+
+That will let you push/pull to and from BitBucket over SSH. Doing it that way
+means you can use public/private key authentication and avoid typing your
+password every single time. A fairly comprehensive guide to that can be found
+[here](http://www.securityfocus.com/infocus/1810). You can ignore the
+server-side configuration; you just need to add your public key on BitBucket's
+account settings page and you should be set.
+
+**UPDATE:**  I didn't realize it before, but BitBucket has a [guide to using SSH with BitBucket](http://bitbucket.org/help/using-ssh/).  It's definitely worth looking at.
+
+Now you should be able to use `hg push` and `hg pull` on your local machine to
+push and pull changes to and from the BitBucket repository. The next step is
+getting it set up on the server side.
+
+### Set Up Your Server
+
+On your server, use `hg clone` to clone the BitBucket repository to wherever
+you want to serve it from. Edit the `.hg/hgrc` file in that one and change the
+default path to the same value as before:
+
+	default = ssh://hg@bitbucket.org/username/repositoryname/
+
+Once again, set up public/private key authentication; this time between the
+server and BitBucket. You can either copy your public and private keys from
+your local machine to the server (if you trust/own it) or you can create a new
+pair and add its public key to your BitBucket account as well.
+
+While you're at it, set up public/private key authentication to go from your
+local machine to your server too. It'll pay off in the long run.
+
+Now that you've got both sides working, you can develop and deploy like so:
+
+* Make changes on your local machine, committing as you go.
+* Push the changes to BitBucket.
+* SSH into your server and pull the changes down.
+* Restart the web server process if necessary.
+
+Not too bad! Instead of manually managing file transfers you can let Mercurial
+do it for you. It'll only pull down the files that have changed, and will
+always put them in exactly the right spot. That's pretty convenient, but we
+can do better.
+
+Weaving it All Together with Fabric
+-----------------------------------
+
+Being able to push and pull is all well and good, but that's still a lot of
+typing. You need to enter a command to push your changes, a command to SSH to
+the server, a command to change to the deploy directory, a command to pull the
+changes, and a command to restart the server process. That's five commands,
+which is four commands too many for me.
+
+To automate the process, I use the wonderful [Fabric][] tool. If you haven't
+seen it before you should take a look. To follow along with the rest of the
+section you should read the examples on the site and install Fabric on your
+local machine.
+
+### My Current Setup
+
+Here's the fabfile I use for deploying my site to my host ([WebFaction][]).
+It's pretty specific to my needs but I'm sure it will give you an idea of
+where to start.
+
+[Fabric]: http://www.nongnu.org/fab/
+[WebFaction]: http://www.webfaction.com?affiliate=sjl
+
+	#!python
+	def prod():
+	    """Set the target to production."""
+	    set(fab_hosts=['sjl.webfactional.com'])
+	    set(fab_key_filename='/Users/sjl/.ssh/stevelosh')
+	    set(remote_app_dir='~/webapps/stevelosh/stevelosh')
+	    set(remote_apache_dir='~/webapps/stevelosh/apache2')
+
+	def deploy():
+	    """Deploy the site."""
+	    require('fab_hosts', provided_by = [prod,])
+	    local("hg push")
+	    run("cd $(remote_app_dir); hg pull; hg update")
+	    run("cd $(remote_app_dir); python2.5 manage.py syncdb")
+	    run("$(remote_apache_dir)/bin/stop; sleep 1; $(remote_apache_dir)/bin/start")
+
+	def debugon():
+	    """Turn debug mode on for the production server."""
+	    require('fab_hosts', provided_by = [prod,])
+	    run("cd $(remote_app_dir); sed -i -e 's/DEBUG = .*/DEBUG = True/' deploy.py")
+	    run("$(remote_apache_dir)/bin/stop; sleep 1; $(remote_apache_dir)/bin/start")
+
+	def debugoff():
+	    """Turn debug mode off for the production server."""
+	    require('fab_hosts', provided_by = [prod,])
+	    run("cd $(remote_app_dir); sed -i -e 's/DEBUG = .*/DEBUG = False/' deploy.py")
+	    run("$(remote_apache_dir)/bin/stop; sleep 1; $(remote_apache_dir)/bin/start")
+
+When I'm finished committing to my local repository and I want to deploy the
+site, I just use the command `fab prod deploy` on my local machine. Fabric
+pushes my local repository to BitBucket, logs into the server (with my public
+key&mdash;no typing in passwords), pulls down the new changes from BitBucket
+and restarts the server process.
+
+I also set up a couple of debug commands so I can type `fab prod debugon` and
+`fab prod debugoff` to change the `settings.DEBUG` option of my Django app.
+Sometimes it's useful to turn on debug to find out exactly why a page is
+breaking on the server.
+
+### Extending It
+
+The reason I split off the `prod` command is so I can set up a separate test
+app (on the server) in the future and reuse the `deploy` and `debug` commands.
+All I'd need to do is add a `test` command, which might look something like
+this:
+
+	#!python
+	def test():
+	    """Set the target to test."""
+	    set(fab_hosts=['sjl.webfactional.com'])
+	    set(fab_key_filename='/Users/sjl/.ssh/stevelosh')
+	    set(remote_app_dir = '~/webapps/stevelosh-test/stevelosh')
+	    set(remote_apache_dir = '~/webapps/stevelosh-test/apache2')
+
+Deploying the test site would then be a simple `fab test deploy` command.
+
+Why Should You Try This?
+------------------------
+
+After you've gotten all of this set up the first time it will start saving you
+time every time you deploy. It also prevents stupid mistakes like FTP'ing your
+files to the wrong directory on the server. It frees you from those headaches
+and lets you concentrate on the real work to be done instead of the busywork.
+Plus setting it up again for a second project is a breeze after you've done it
+once.
+
+Obviously the exact details of this won't be a perfect fit for everyone. Maybe
+you prefer using git and [GitHub][] for version control. I'm sure there's a
+similar way to automate the process on that side of the fence. If you decide
+to write something about the details of that please let me know and I'll link
+it here.
+
+My hope is that this will at least give you some ideas about saving yourself
+some time. If that helps you create better websites, I'll be happy. Please
+feel free to comment with any questions or thoughts you have!
+
+[GitHub]: http://github.com/
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/01/going-open-source.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,139 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Going Open Source"
+    snip: "Why I’m making the code to this website public."
+    created: 2009-01-13 20:08:56
+%}
+
+{% block article %}
+
+Well, I've finally taken the plunge and made this site open source. It's held
+in a [Mercurial][] repository, but you can view or download the source code
+from <http://bitbucket.org/sjl/stevelosh/> without any special tools.
+
+The site was built with the [Django][] framework. If you want to know more
+check out the [project page][]. This post isn't going to duplicate what's
+there; instead I want to write about why I made the site open source at all.
+There are a couple of main reasons, and not *all* of them are selfish!
+
+[Mercurial]: http://www.selenic.com/mercurial/wiki/
+[Django]: http://djangoproject.com/
+[project page]: /projects/stevelosh-com
+
+I Get More Traffic
+------------------
+
+The first reason to make a site open source is to try to get more hits. You
+certainly don't *lose* any hits from doing it, and when developers find your
+link on places like [DjangoSites][] they might be more inclined to visit if
+they knew they could look at the source code later.
+
+You also have the chance to post on [Twitter][], [Tumblr][], or other places
+about the source code of the site. Each of those posts can expose more people
+to the website. It's easy to overdo this though. I heartily agree with the
+sentiments of
+[howtousetwitterformarketingandpr.com](http://howtousetwitterformarketingandpr.com)
+on that issue.
+
+Don't worry, I won't be obnoxious about it.
+
+[DjangoSites]: http://djangosites.org/
+[Twitter]: http://twitter.com/
+[Tumblr]: http://tumblr.com/
+
+I Can Give Back to the (Programming) Community
+----------------------------------------------
+
+Yeah, I know.  It sounds cliched, but it's true.  
+
+The open source community has produced a *ridiculous* amount of software, some
+of which we use every day. Software like [Apache][], [Django][], and countless
+others simply wouldn't exist in anything remotely close to their current
+forms.
+
+Being able to look at the source code for a particular project can be
+extremely helpful to someone trying to learn how to do something similar.
+Instead of firing up an email client and sending a message to the creator they
+can simply look at how it works themselves. They can download it, tweak it,
+break it, and figure out what makes it tick. There's no substitute for that.
+
+I strongly believe that the world would be a better place if everyone shared
+their knowledge (in all fields) and we all learned from each other. In some
+cases it's simply not practical, but more often than not I think people want
+to horde their knowledge and feel superior. Sure, that might be nice for your
+ego, but does it really make the world a happier, more beautiful place to
+live?
+
+[Apache]: http://apache.org/
+
+I Might Get Free Code!
+----------------------
+
+Well, probably not, but who knows? Maybe some developer has a lot of free time
+on his or her hands?
+
+Distributed version control systems like [Mercurial][] make it extremely easy
+to help out with open source projects. For example, if you were looking
+through my code and saw a bug that you wanted to fix, you could do the
+following:
+
+* Clone the repository to your own machine. * Fix the bug in that local copy,
+committing to your local repository as you go. * Go back to the website and
+click the "Pull Request" button. * I review the changes. * If I like them I
+press a button to merge them into the main repository.
+
+Once the changes are in the main repository I just run a single script to
+redeploy the site as usual and the changes are live. It's really an almost
+painless process. Compare that to something like Subversion or (ick) CVS:
+
+* Check out the repository to your own machine.
+* Fix the bug in that local copy, without committing (don't mess up!).
+* Create a patch using diff or something similar.
+* Email me the patch.
+* I review the changes.
+* If I like them I check out a fresh copy of the repository.
+* I apply the patch to this copy.
+* I merge the patch back into the main repository.
+
+It's much more difficult because I don't want to just give any anonymous
+person commit access to my repository.
+
+It Makes Me Fix My Damn Code
+----------------------------
+
+This is probably the most tangible and important benefit of my open sourcing
+this site. It forced me to rewrite parts of the code that weren't secure and
+do it the right way.
+
+Passwords stored in source control? Yeah, *definitely* a bad thing.
+
+Of course, it *was* kind of a pain in the ass to refactor a bunch of stuff.
+Really, though, the main problem I had was my own procrastination and going
+open source was a good nudge. Plus when I start work on another site I'll know
+how to do it right the first time.
+
+Aside from major security and privacy issues, it also gives me a big incentive
+to clean up my code and make it more elegant. Clean, elegant code makes me
+happy. It's less likely to have bugs (because there are fewer places for them
+to hide) and it's far easier to maintain in the long run.
+
+It's also simply more fun to read and work with.
+
+You Should Probably Try It
+--------------------------
+
+Obviously not all software is appropriate for open sourcing, but if you've got
+a pet project that you've been working and you think it might benefit from a
+few more sets of eyes, try it!
+
+You don't need to spend money or configure much of anything to share your
+code; sites like [BitBucket][] and [GitHub][] offer free hosting and great
+interfaces for repositories of open source code.
+
+If you have any questions or comments I'd love to hear them!
+
+[BitBucket]: http://bitbucket.org/
+[GitHub]: http://github.com/
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/01/site-redesign.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,45 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Site Redesign"
+    snip: "Yeah, I know.  Again."
+    created: 2009-01-11 17:58:23
+%}
+
+{% block article %}
+
+Well, I've redesigned the site again. This time it's all me. I built the site
+from the ground up with [Django][] and [Python][]. Why? Several reasons:
+
+* I already pay for hosting at [WebFaction][] for other sites so also paying [Squarespace][] for my personal one was too wasteful.
+* I wanted to practice designing another site with [Django][].
+* I wanted more flexibility than [Squarespace][] supports and I'm not afraid to get my hands dirty with code.
+
+If you want to know more about how I created the site, check out the site's
+[project page][].
+
+Moving over
+-----------
+
+I've tried to make transitioning to the new site as easy as possible. For
+example, I set up the urls so that links to the entries on the old blog will
+redirect to entries on the new one if they exist.
+
+Coming soon
+-----------
+
+I'm going to work on porting over more of the old blog entries in the next day
+or two. I don't want to bring them all over; just the best ones.
+
+I'm also going to implement an RSS feed that will encompass projects and blog
+entries.
+
+Let me know what you think!
+
+[Python]: http://python.org/
+[Django]: http://djangoproject.com/
+[WebFaction]: http://webfaction.com/
+[Squarespace]: http://www.squarespace.com/
+[project page]: /projects/stevelosh-com
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/02/how-and-why-i-dj.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,211 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "How &amp; Why I DJ"
+    snip: "I like playing music for dancers."
+    created: 2009-02-06 17:53:44
+%}
+
+{% block article %}
+
+I've been DJ'ing at swing and blues dances for a while now. It's extremely fun
+and rewarding. I've got a system that I use to keep myself sane while doing it
+and I felt like sharing. Let me know what you think!
+
+[TOC]
+
+## How I Started
+
+When I was just starting to get really interested in dancing I didn't think
+I'd want to DJ much. I thought it would be a lot of work and that I'd hate
+having to stay near a computer during a dance. It just didn't seem like very
+much fun.
+
+The only reason I began to try my hand at it was because we needed to have
+good music to play at RIT Swing Dance Club when my old roommates and I started
+teaching there. I wanted the other people to have a good time and hear the
+awesome music that we love dancing to. I figured that it didn't need to be a
+big deal; I'd just find some cool music and play it at club.
+
+Once I started, I realized that I really like being able to play great music
+for other people to dance to. It sounds cliche, but it really *is* rewarding.
+There's something special about having a kind of control over an entire dance
+floor.
+
+After I became comfortable DJ'ing at club it was only a matter of time before
+I started [signing up to DJ][ljdj] at [Lindy Jam][] and then playing music at
+our little blues parties. I love it. DJ'ing is good for me &mdash; it forces
+me to look for interesting new music and really *listen* to it to hear how it
+works. Really listening (without dancing) closely to swing or blues music is
+something that I don't think enough dancers do.
+
+## Where Do I Find Music?
+
+Most of the music I play comes from [eMusic][]. It's a great site &mdash; you
+pay $15 and get about 40 tracks per month. That's far cheaper than iTunes and
+it's all DRM-free mp3 files. They have a great collection of jazz and blues
+(and a lot of indie and classical music too). I highly recommend them if
+you're looking for some awesome music.
+
+Previously I've wanted nothing to do with iTunes because of the DRM.
+Thankfully Apple has announced that they've convinced the record labels to
+allow DRM-free downloads of everything. I'll still get most of my music from
+eMusic (it's cheaper) but if they don't have a song I want I'll definitely
+look on iTunes.
+
+As for CDs and vinyl, I do occasionally buy and rip some, but for the most
+part digital music is simply faster, easier, and cheaper to use.
+
+## Sorting My Music
+
+Over the past couple of years I've turned into a pretty organized person. If I
+don't have a good method of sorting and organizing my music I'll go crazy when
+I try to DJ. I've developed a way of organizing everything over the years I've
+been DJ'ing which seems to work pretty well for me.
+
+### "Danceable" Music
+
+The first thing I do when I download a new CD from eMusic is skim each track
+and decide if it's even remotely danceable. If it's got a beat I can dance to
+at all, it goes into my "Lindy & Blues" playlist in iTunes. I don't worry
+about how good the song is &mdash; the important part for me is getting the
+decent songs into that playlist so I don't forget about them.
+
+### Tempo
+
+My next step is tagging danceable songs with BPM (beats per minute)
+information. This is really nice to know when you're out at a dane and
+thinking: "I should play a song that's a bit faster than that last one."
+
+I've experimented with a couple of different methods in the past but they all
+seemed pretty cumbersome. The solution came in the form of this [Tempo
+Widget][] for my Mac's dashboard. Click the button on each beat, double click
+the numbers to save the BPM to the currently playing iTunes song.
+
+That's nice, but it's not enough for a nerd like me. The mouse is so slow;
+what I really needed was a way to use the keyboard for everything so I could
+fly through tagging my songs in less than 15 seconds each. I opened up the
+code for the widget and added a couple things. I can press any key on a beat
+instead of clicking the button, and I can hit Cmd+S to save the BPM to the
+iTunes song instead of double clicking the numbers.
+
+I also use [Quicksilver][] to add keyboard shortcuts to move to the
+next/previous song in iTunes. Now that I've got all that done, when I want to
+tag a bunch of new songs with BPMs I can do this:
+
+1. Start playing the first song and open up the dashboard.
+2. Press any key on each beat until I have a consistent BPM displaying.
+3. Press Cmd+S to save the BPM to the song.
+4. Press Cmd+Option+Ctrl+Right Arrow to move to the next song.
+5. Repeat steps 2-5 for each song.
+
+It usually takes me 15 seconds or less per song and saves me a ton of time (I
+have about 900 songs tagged with BPMs right now!). If you're interested in my
+modified version of the Tempo Widget let me know.
+
+### Rating (Smartly)
+
+Let's face it: some songs are better than others. Some songs are fun to dance
+to, but others almost *force* you out of your seat. I like to be able to
+glance at my playlist and have a rough idea of which *really awesome* songs
+I've got at a specific tempo.
+
+Some people might say: "You should know all of your music by heart and
+shouldn't need to rely on ratings." I disagree &mdash; maybe I'm just not as
+diligent in studying but there's no way I could remember every single song in
+my playlist. Of course you should know your music, but that doesn't mean you
+can't use whatever tools you like to make your DJ'ing even more effective.
+Ratings help me remember to play a song that I might otherwise have forgotten
+about and let me see what my options are if I really need a fantastic song
+*right now*.
+
+Unfortunately I didn't start rating my danceable songs until a month or two
+ago and so I'm only about halfway through. One thing that helps is iTunes'
+Smart Playlists. I can create a smart playlist that only shows me songs that
+are in my "Lindy & Blues" playlist but aren't yet rated.
+
+![Unrated Smart Playlist Screenshot](/media/images{{parent_url}}/dj-playlist-unrated.png "Unrated Smart Playlist")
+
+I have an iPod as well, so when I'm out and listening to my music I can set
+the rating right on the iPod. When I get back to my computer I plug in the
+iPod and it syncs the ratings back to iTunes for me.
+
+## At a Dance
+
+All of the steps I've talked about so far have one goal: to make playing great
+music at an actual dance easier.
+
+### Previewing
+
+I rarely preview songs before I play them; I know my collection pretty well
+and usually have a good idea whether or not a song will fit. Still, it's
+definitely nice to be able to hear a song now and then.
+
+Some DJ's really love external sound cards which let you have two music
+players open on your machine; one plays the music going to the room speakers
+and the other plays into a set of headphones. I don't use this setup for a few
+reasons:
+
+* I can't be bothered to buy an external sound card.  I know, I'm lazy.
+* Computers are tricky, and adding another sound card into the mix makes
+  things trickier. Having another audio interface often causes some headaches
+  when you're ready to DJ and no sound is coming out of one port because
+  there's a configuration option messed up somewhere.
+* I don't trust myself. I can easily see myself accidentally trying to preview
+  on the music player that's going to the room.
+
+What do I do instead? I use my iPod. Sure, the interface isn't as easy to
+navigate as a music player on a laptop, but it doesn't cost any extra money (I
+have it anyway) and there's no chance of accidentally messing up the currently
+playing song.
+
+### Running Playlists
+
+Throughout the night as I decide which songs I want to play I put them in two
+separate lists. First they go into my "Short List" which is usually around
+five to ten songs that I think I'll want to play fairly soon. That gives me
+easy access to songs I'll probably play soon.
+
+The "Running" playlist is the one that's actually playing through the
+speakers. I usually have one or two songs queued up ahead of time in case I
+get distracted from my laptop for a bit.
+
+### Sorting on the Fly
+
+All the work I put into tagging and rating my music pays off when I'm actually
+trying to decide what to play next. When I'm looking through my collection my
+iTunes window will usually look like this (except for being slightly bigger
+and having the sidebar showing):
+
+![Sorted Danceable Playlist Screenshot](/media/images{{parent_url}}/dj-playlist-sorting.png "Sorted Danceable Playlist")
+
+I can use the search bar in the upper right if I'm looking for something
+specific. I can sort by BPM if I know I want a song at a rough tempo. The
+ratings draw my eyes to the songs that I love the most. The comments are there
+to remind me about songs that have long intro/outros, double timed sections,
+etc. Having all of that at my fingers makes it much easier for me to find
+exactly what I want and get it to the speakers.
+
+## And So...
+
+I wrote this because I wanted to share how and why I DJ for dancers. If you're
+a DJ, I hope I've given you a couple of ideas for new tricks to make your job
+easier. **Let me know what you think in the comments!**
+
+If you don't DJ but think you might want to, great! Please don't be scared off
+by my absurdly organized workflow &mdash; just because it works for me doesn't
+mean you have to do it. Find some good music and [sign up to DJ at Lindy
+Jam][ljdj]! If you think two hours is too long for you as when you're first
+learning to DJ just ask myself, Matt, Jesse, Mike or Beth if we'll share the
+night half & half with you. If you have any questions please let me know!
+
+
+[Lindy Jam]: http://lindyjam.com/
+[ljdj]: http://lindyjam.com/schedule/
+[eMusic]: http://emusic.com/
+[Quicksilver]: http://www.blacktree.com/
+[Tempo Widget]: http://mac.softpedia.com/get/Dashboard-Widgets/Music/Tempo-Widget.shtml
+
+
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/02/how-i-shoot-dances.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,351 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "How I Shoot Dances"
+    snip: "Slow shutter and flash."
+    created: 2009-02-09 18:04:36
+%}
+
+{% block article %}
+
+Last weekend [Gordon Webster][] came to Rochester, NY to play a dance at The
+Keg. It was awesome (of course) and everyone had a great time.
+
+I took a lot of photos during the course of the night (around 360 actually)
+and some of them turned out pretty nice. A few people have wondered how I got
+the look I did, so I decided to write a post about it.
+
+I'm assuming you know what basic terms like aperture and shutter speed mean.
+If not, look for a post over at [LindyBloggers][] fairly soon about shooting
+dances with a point-and-shoot camera.
+
+[Gordon Webster]: http://webster.suresong.com/
+[LindyBloggers]: http://lindybloggers.com/
+
+Shooting Dancers is Tough
+-------------------------
+
+One of the reasons I got into photography seriously was so that I could shoot
+dancers and musicians. I've since branched out and become interested in a lot
+of other aspects of photography, but dancing is a huge part of my life and
+photographing dancers is still something I absolutely love.
+
+I (like many others) thought that getting a DSLR would let me take awesome
+dancing photos with a bit of practice. Well, it's not that simple. Dances are
+one of the hardest things I shoot for a couple of reasons.
+
+### We Move
+
+Dancing, especially in a dance like Lindy Hop, involves a lot of movement. It
+makes focusing a huge pain unless you've got *really* good eyes. I don't. When
+I first started out the majority (at least 70%) of my dance photos were out of
+focus. It's much more difficult than shooting a still (or even slowly moving)
+target.
+
+Moving quickly also means you need a fast shutter speed if you want anything
+to be sharp. You can focus perfectly but that won't freeze any movement. This
+wouldn't be an issue if it wasn't for the second main problem.
+
+### The Lighting at Dances is Awful
+
+Seriously, it's terrible. It's always fairly dark to set the mood; you don't
+want to dance in a brightly lit place unless you're competing. To make matters
+worse, it's almost always ridiculously uneven. Part of the room with usually
+be two or three stops darker than the rest.
+
+Only shooting in one place helps, but is fairy boring. A lot of people will
+stay in the same general area for most of the night (damn cliques!) and so if
+you only shoot one section of the floor you'll miss a lot of people.
+
+What Doesn't Work (for Me (Usually))
+------------------------------------
+
+I've tried a couple of different techniques to overcome these problems. Some
+of them work in some situations but most of the time they leave me unhappy.
+
+<a href="http://www.flickr.com/photos/sjl7678/2449590741/"
+   title="GirlJamSunday-5512 by Steve Losh, on Flickr">
+    <img src="http://farm3.static.flickr.com/2076/2449590741_b47a5ced4c_m.jpg"
+         width="161" height="240" alt="GirlJamSunday-5512"
+         class="right" />
+</a>
+
+### Fast Primes, High ISO
+
+The first remedy I turned to was buying a fast prime lens (Pentax 50mm f/1.4)
+so that it would let in more light. With that lens I would turn up the ISO to
+1600 or so to get even more sensitivity and hope for the best. This kind of
+works, but has some issues.
+
+#### The Good
+
+Shooting with a fast prime means I only have to carry one lens around and
+don't need to change it during the night. They're usually pretty light too, so
+they're easier to work with. 50mm is a nice focal length that lets you stand
+far enough away to not get kicked. You also don't need to annoy people with
+flash.
+
+The wide apertures let more light in so you can actually get some decently
+exposed photos at workable shutter speeds. The ISO isn't much of an problem as
+long as you expose the photo right (if you have to bring up the exposure more
+than a half stop in post it looks terrible).
+
+This solution really excels if you're shooting classes or workshops. The light
+there is usually much better than at actual dances but still not ideal. The
+wide apertures let you soak up all of that light and you can get some really
+nice photos. The example in this section was taken at Girl Jam last year
+during one of the classes with my 50mm.
+
+#### The Bad
+
+Focusing on moving dancers is hard enough at "normal" apertures; trying to
+nail the focus when you've only got six inches of depth of field at f/1.4 is
+*nearly fucking impossible*. Maybe other photographers are better at manually
+focusing or have amazing Canon/Nikon cameras that can focus on a black cat in
+a darkroom, but I'm not and I don't.
+
+The focal length of most fast primes is generally around 50mm. This isn't too
+bad, but I've grown to really love wide angle lenses. 50mm feels too far and
+detached for my taste. Yours may be different, so give it a try.
+
+<a href="http://www.flickr.com/photos/sjl7678/3256610463/"
+   title="LindyJam-0095 by Steve Losh, on Flickr">
+    <img src="http://farm4.static.flickr.com/3400/3256610463_5465877459_m.jpg"
+         width="181" height="240" alt="LindyJam-0095"
+         class="right" />
+</a>
+
+### Bounced Flash, Max Sync Speed
+
+For a while I was adamant that I would never use flash. I figured it would be
+annoying and that the "unnatural" light from the flash would somehow look
+wrong. I avoided it for a while in favor of fast primes and "natural" light.
+
+Eventually I noticed that some other photographers shot with flash at dances
+and it didn't annoy me (while dancing) at all. I decided to give it a shot and
+see how it worked, especially since I was getting really into [Strobist][] and
+studio lighting at the time.
+
+[Strobist]: http://strobist.com/
+
+The basic idea is that you use an external flash (preferably off camera,
+synched with a cord or radio triggers) and bounce the light from the ceiling
+to get more even coverage. You set the aperture to something moderate like f/4
+or f/5.6 and the ISO fairly low. You turn the shutter speed down as low as it
+will go and still sync up and let the strobe do the hard work.
+
+#### The Good
+
+You get sharp photos! What's more, focusing is no longer something you will
+curse vehemently! When you're shooting at f/4 or f/5.6 you have a good amount
+of depth of field so the focus doesn't have to be absolutely perfect.
+
+The flash only lasts about 1/1000 of a second. No one moves much in that time,
+so you get perfectly sharp photos despite the movement.
+
+Now that you're not relying on wide apertures you can start using different
+focal lengths instead of sticking with the fast prime or two that you have.
+You could even use a zoom lens if you don't want to change lenses all the
+time.
+
+#### The Bad
+
+Bouncing from the ceiling is far, far better than keeping your flash on camera
+and pointing it straight at the subjects, but unless the room has obnoxiously
+high ceilings you're still going to get a lot of falloff towards the back of
+the room. You might not mind; it *does* help isolate the subjects from their
+surroundings but I found myself getting tired of it pretty quickly.
+
+You also have to carry a flash, sync cord or triggers, and extra batteries
+around which is kind of a pain. I don't mind, but if you like traveling light
+it could bother you.
+
+This section's example is one of the better results of this technique: Tango
+Cafe's ceilings are very high so the light is pretty even everywhere. High
+ceilings come at a price, however: you need more power from the flash to
+illuminate everything and so can't shoot as fast.
+
+Rethinking My Approach
+----------------------
+
+After using these two methods for a while I stopped and looked at my photos. I
+wasn't as happy with them as I would have liked. I sat down and asked myself:
+"Why is that?" The photos were exposed well and aside from the focusing
+mishaps were pretty sharp. What was missing?
+
+<a href="http://www.flickr.com/photos/sjl7678/299107896/"
+   title="CIMG0171.JPG by Steve Losh, on Flickr">
+    <img src="http://farm1.static.flickr.com/120/299107896_fbec7e2df7_m.jpg"
+         width="240" height="155" alt="CIMG0171.JPG"
+         class="right" />
+</a>
+
+Eventually I came up with my answer: "Movement." Lindy Hop is very much about
+movement; it's one of the most important parts of the dance, maybe even *the*
+most important part. Getting tack sharp photos is great, but it's very hard to
+convey movement with them unless you're a much better photographer than I am.
+
+Most people are not photographers. Most dancers are also not photographers.
+The majority of Lindy Hoppers will take photos with small point-and-shoot
+cameras, *if* they can drag themselves away from dancing for a little while!
+
+The result is that we don't usually see many dance photos (because we're too
+busy dancing to take them) and the ones that we do see are usually blurry
+(because point and shoot cameras in their default modes are just not equipped
+to take sharp ones).
+
+<a href="http://www.flickr.com/photos/sjl7678/299107792/"
+   title="CIMG0141.JPG by Steve Losh, on Flickr">
+    <img src="http://farm1.static.flickr.com/118/299107792_0b4907245f_m.jpg"
+         width="240" height="180" alt="CIMG0141.JPG"
+         class="right" />
+</a>
+
+Even with their flaws, *we love them* because they're the few photographic
+memories we have of some of the best nights of our lives.
+
+I wanted people to have the same feeling toward my photography as they do
+toward these informal snapshots. I wanted to capture the essence of these
+pictures we're so grateful for but use my experience to make something even
+better.
+
+I think I've finally figured out how.
+
+Using Everything
+----------------
+
+What evokes the feeling of movement in the point-and-shoot shots we look at? I
+think it's the blurriness. Our culture is used to looking at photographs and
+we know that "blurry photograph" usually means "moving subject" even if we're
+not always 100% clear on the physics of it.
+
+<a href="http://www.flickr.com/photos/sjl7678/3264591984/"
+   title="GW-0453 by Steve Losh, on Flickr">
+    <img src="http://farm1.static.flickr.com/250/3264591984_296047fb19_m.jpg"
+         width="181" height="240" alt="GW-0453"
+         class="right" />
+</a>
+
+As photographers, we know what causes it. A subject moving while the shutter
+is open produces blur. Longer shutter speeds mean more blur. The little
+cameras that most of our memories come from simply don't have the aperture or
+sensitivity of our hefty DSLRs &ndash; all the poor little things can do is
+leave their shutters open a bit longer to get the light they need. That's why
+those cameras make blurry photos with their default settings.
+
+So how can I add some blurriness to my images? Use a slower shutter speed! I
+also want to keep some sharpness though, so the dancers are more recognizable.
+To do this, I use flash *at the same time*. The flash freezes the subjects
+enough to make them look good and then slow shutter speed and ambient light
+take over to add some movement.
+
+### The Technique
+
+What do you need to do this kind of thing? You can get by with any modern
+camera with a built-in flash, but to really have the flexibility that will
+make you happy you need the following things:
+
+* **A camera with a hot shoe or PC jack and manual controls**.  I use a Pentax K20D when I feel like lugging it out and a Canon G10 when I don't.
+* **An external flash.**  I use an $80 Vivitar 285hv which will work with anything, so no complaining about how your camera maker only sells $400 speedlights.
+* **A way to sync your flash with the camera.**  Some of the more expensive flashes have a wireless mode.  If not, you can buy radio triggers for $60 or so, or buy a sync cable for $15 to $20.  Trust me, having the flash *off* of the camera makes things so much easier.
+
+<a href="http://www.flickr.com/photos/sjl7678/3264540604/"
+   title="GW-0290 by Steve Losh, on Flickr">
+    <img src="http://farm1.static.flickr.com/195/3264540604_f4665b50e6_m.jpg"
+         width="240" height="181" alt="GW-0290" 
+         class="right" />
+</a>
+
+#### Step 1 &ndash; Dial in the Flash
+
+The first step to getting this look is to figure out what kind of exposure you
+need with *the flash alone* to get a well-lit shot.
+
+Turn your shutter speed down to the fastest it will sync (1/180th is usually
+fine) and use trial and error to find a nice combination of aperture, ISO and
+flash power. The actual numbers will depend on several things: how low the
+ceilings are, how powerful your flash is, etc.
+
+Aim for the lowest flash power you can while still keeping a good exposure, a
+narrow enough aperture to make focusing easy, and modest ISO noise. Once you
+figure it out you can probably keep those settings for the rest of the night,
+unless the ceilings are higher on one side of the room or something else
+equally annoying.
+
+#### Step 2 &ndash; Dial in the Ambient
+
+This is the step that adds the movement. First, tone down your flash-only
+exposure by a half or whole stop. Do this by reducing the ISO, aperture, or
+flash power; any of those is fine.
+
+Now that your photo is underexposed, turn off the flash. It will probably be
+completely black now. *Do not touch the ISO or aperture to fix this.* Lengthen
+the shutter speed until you're about two stops underexposed; it will be blurry
+and dark as hell but this is what you want right now.
+
+<a href="http://www.flickr.com/photos/sjl7678/3263800481/"
+   title="GW-0580 by Steve Losh, on Flickr">
+    <img src="http://farm1.static.flickr.com/196/3263800481_9ebf0a47f3_m.jpg"
+         width="240" height="181" alt="GW-0580"
+         class="right" />
+</a>
+
+#### Step 3 &ndash; Combine and Adjust
+
+Turn the flash back on. Do not touch any other settings &ndash; flip the
+switch on the flash and start shooting. This will let the flash illuminate the
+subjects (because you dialed in the power, ISO and aperture before and haven't
+changed them) and the ambient fill in and add movement (because you adjusted
+the shutter speed).
+
+Your first few shots will probably be underexposed or overexposed and have too
+much or too little blur. Don't worry, it always takes me at least a half hour
+to start taking decent photos this way. You really need to play with the
+settings as you go to find out what's going to work for the lighting *that
+night*.
+
+#### Things to Watch Out For
+
+There are a couple of tricky parts to this style of shooting that I'll
+mention. First I'll talk about the typical problems you'll see right away.
+More than one of these certainly might apply; fix them one at a time.
+
+<a href="http://www.flickr.com/photos/sjl7678/3263819663/"
+   title="GW-0656 by Steve Losh, on Flickr">
+    <img src="http://farm1.static.flickr.com/192/3263819663_4f97c18da4_m.jpg"
+         width="181" height="240" alt="GW-0656"
+         class="right" /></a>
+
+* **If the background is dark or there is not enough blur,** you need to use a longer shutter speed to let more ambient light in.
+* **If the dancers are not sharp enough,** you need *more* flash power.  Turn it up a little bit at a time.
+* **If people's shirts, faces and limbs are overexposed *and not blurry*,** you need to turn down the flash.  Bring it down a bit by reducing the power, narrowing the aperture or reducing the ISO.
+* **If shirts, faces and limbs are overexposed *and blurry*,** you need to shorten the shutter speed to let less ambient light in.
+
+I'm warning you now, fixing one of these will probably fuck something else up.
+It can be really infuriating, but if you slow down, stay calm and think
+through it logically you'll be able to narrow it down and figure out what you
+need. It's a really good feeling when you finally nail it.
+
+There are two other tricky problems that I'm still working on myself:
+
+* **Dances are unevenly lit.**  When you walk over to the other side of the room to shoot, you'll have to adjust the shutter speed to compensate for the different amount of ambient light.  You really only have a range of about half a stop where the ambient gives you the right amount of blur, so you have to be careful and stay on your toes.
+* **Watch where you bounce.**  In rooms with low ceilings, where you point the flash on the ceiling has a huge effect on the lighting.  You need to be conscious of what part of the ceiling you're bouncing from to get good results.
+
+Good Luck!
+----------
+
+I hope this post helped you out. Even if you hate how my photos look and don't
+want to make anything like them, at least it will show you what *not* to do.
+I'd love to hear comments or advice on what you like or don't like, and what I
+could do better. If you've got questions I'll do my best to answer them too!
+
+Now go dance, have fun, and make beautiful photographs so we can all remember
+the fantastic events we make happen!
+
+<a href="http://www.flickr.com/photos/sjl7678/3263760493/"
+   title="GW-0438 by Steve Losh, on Flickr">
+    <img src="http://farm1.static.flickr.com/196/3263760493_08c525cfe7.jpg"
+         width="500" height="377" alt="GW-0438" />
+</a>
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/03/candy-colored-terminal.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,95 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Candy Colored Terminal"
+    snip: "Better colors for the OS X Terminal."
+    created: 2009-03-18 18:26:28
+%}
+
+{% block article %}
+
+Yesterday I wrote a blog post about [adding Mercurial information to your bash
+prompt](/blog/entry/2009/3/17/mercurial-bash-prompts/). Almost all of the
+comments on that entry so far have been asking for the colors I used in the
+Terminal screenshots, so that's what this post is for.
+
+The first section of this entry will be able overcoming the limitations of the
+OS X Terminal application. Skip it if you're using another (better) terminal
+application.
+
+The OS X Terminal and Colors
+----------------------------
+
+OS X's Terminal doesn't support 256-color mode. I have no idea why. Apple, if
+you're reading, *please fix this*. Because of this, if you want to make the
+colors prettier you've only got the 16 ANSI colors to work with.
+
+Once again, Apple fails hard with Terminal.app. You can't change the 16 ANSI
+colors -- you can only change the default text color and background.
+Seriously, Apple, what the hell?
+
+To fix this, you'll need to install [SIMBL][] and [TerminalColors][]. Follow
+the instructions on those pages and be sure to restart Terminal once you've
+finished. Now you can change the ANSI colors be hitting the "More" button
+under the text color settings.
+
+[SIMBL]: http://www.culater.net/software/SIMBL/SIMBL.php
+[TerminalColors]: http://ciaranwal.sh/2007/11/01/customising-colours-in-leopard-terminal
+
+Picking Some Colors
+-------------------
+
+Now that we've beaten Terminal.app into compliance, it's time to pick some
+pretty colors. I love the [Monokai][] color scheme for [TextMate][] and so I
+based my choices on that. Here's what it looks like:
+
+![Screenshot of my Terminal, with colors.](/media/images{{parent_url}}/terminal-colors.png "My Terminal colors.")
+
+[Monokai]: http://www.monokai.nl/blog/2006/07/15/textmate-color-theme/
+[TextMate]: http://macromates.com/
+
+Here are the RGB values I'm using:
+
+* Black: 0, 0, 0
+* Red: 229, 34, 34
+* Green: 166, 227, 45
+* Yellow: 252, 149, 30
+* Blue: 196, 141, 255
+* Magenta: 250, 37, 115
+* Cyan: 103, 217, 240
+* White: 242, 242, 242
+
+The window background is just set to plain old 0, 0, 0 with a 95% opacity.
+
+Not all of the colors match the names: "blue" is actually more of a purple,
+and "yellow" is much more orange. That doesn't really matter much though
+because they're different enough from each other to still be useful.
+
+Now that the colors are set up you can use them in the normal way. Check out
+[this guide][] if you don't know how to do that. Here's the full code for my
+bash prompt:
+
+**UPDATE:** I've cleaned up the code a lot thanks to the kind folks in #bash
+on freenode who helped set me straight on bash quoting and escaping. I've also
+switched to using my [hg-prompt extension](/projects/hg-prompt/) for the
+repository information.
+
+[this guide]: http://www.ibm.com/developerworks/linux/library/l-tip-prompt/
+
+    #!bash
+    D=$'\e[37;40m'
+    PINK=$'\e[35;40m'
+    GREEN=$'\e[32;40m'
+    ORANGE=$'\e[33;40m'
+    
+    hg_ps1() {
+        hg prompt "{${D} on ${PINK}{branch}}{${D} at ${ORANGE}{bookmark}}{${GREEN}{status}}" 2> /dev/null
+    }
+    
+    export PS1='\n${PINK}\u ${D}at ${ORANGE}\h ${D}in ${GREEN}\w$(hg_ps1)\
+    ${D}\n$ '
+
+I hope this helps! If you'd like to share your color schemes or tell me how to
+make the code for my prompt a bit less ugly, please comment!
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/03/mercurial-bash-prompts.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,184 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Mercurial Bash Prompts"
+    snip: "Always know where you are."
+    created: 2009-03-17 21:34:55
+%}
+
+{% block article %}
+
+I've been spending a lot of time in the Terminal lately. I use bash, and it
+lets you configure the prompt pretty much however you want. I won't go into
+how to do the most basic configuration here - if you want to get up to speed
+check out this [guide][].
+
+In this post I'm just going to talk about one simple addition that I
+personally find very helpful: displaying the current branch of a [Mercurial][]
+repository.
+
+Update: the hg-prompt Extension
+---------------
+
+I swear, this is the last time I'm updating this entry. I went ahead and made
+an extension for Mercurial called
+[hg-prompt](http://stevelosh.com/projects/hg-prompt/) that does everything
+much more elegantly. **Use that instead!**
+
+[guide]: http://www.ibm.com/developerworks/linux/library/l-tip-prompt/
+[Mercurial]: http://www.selenic.com/mercurial/wiki/
+[git version]: http://gist.github.com/31631
+
+My Starting Point
+-----------------
+
+Here's what my prompt looked like a couple of days ago:
+
+![My bash prompt without the branch displayed](/media/images{{parent_url}}/prompt-without-branch.png "My bash prompt without the branch displayed.")
+
+Here's the code in my `.bashrc` file to create it. I've stripped out the color
+information to save space.
+
+    #!bash
+    export PS1='\n\u at \h in \w\n$ '
+
+I use the same prompt on every computer I work with, so with this prompt I can
+see which user I'm logged in as, which machine I'm on, and where in the
+filesystem I am. It's a lot of useful information at a glance but doesn't seem
+too cluttered.
+
+I have a linebreak in there because the filesystem path can get pretty long.
+If I kept it all on one line most of my commands would be wrapped around
+anyway, which I find harder to read.
+
+Adding the Mercurial Branch
+---------------------------
+
+I use Mercurial for version control, and I use branches quite a bit when I'm
+developing. One problem with this is that it's easy to forget which branch I'm
+on at a given moment. I *could* just use `hg branch` to find out, but that
+gets tedious to type, even when aliased to something like `hb`.
+
+A few days ago I got the idea that I could just display the current branch on
+my prompt whenever I'm in a directory that's part of a repository. Here's what
+my prompt looks like now:
+
+![My bash prompt with the branch displayed](/media/images{{parent_url}}/prompt-with-branch.png "My bash prompt with the branch displayed.")
+
+And here's the code in my `.bashrc` that does it:
+
+    #!bash
+    hg_in_repo() {
+        hg branch 2> /dev/null | awk '{print "on "}'
+    }
+
+    hg_branch() {
+        hg branch 2> /dev/null | awk '{print $1}'
+    }
+
+    export PS1='\n\u at \h in \w $(hg_in_repo)$(hg_branch)\n$ '
+
+The `on branchname` piece is only displayed when you're in a directory that's
+part of a Mercurial repository.
+
+I've split it up into two separate functions because I wanted to have `on` and
+`branchname` displayed in two different colors. I couldn't seem to include the
+color codes in the awk command, so I split it up and put the colors in the
+export statement with the rest of them. If you don't care about colors (or
+don't mind having both words the same color) you can just collapse it into one
+function.
+
+Updated: Is It Dirty?
+---------------------
+
+After I posted this entry Matt Kemp commented with a link to a [git
+version][]. One feature that version has is a simple indicator of whether or
+not the repository you're in is dirty. I ported it to Mercurial and here's the
+result:
+
+![My bash prompt with the branch and dirty indicator displayed](/media/images{{parent_url}}/prompt-with-dirty.png "My bash prompt with the branch and dirty indicator displayed.")
+
+And the code in `.bashrc`:
+
+    #!bash
+    hg_dirty() {
+        hg status --no-color 2> /dev/null \
+        | awk '$1 == "?" { print "?" } $1 != "?" { print "!" }' \
+        | sort | uniq | head -c1
+    }
+    
+    hg_in_repo() {
+        [[ `hg branch 2> /dev/null` ]] && echo 'on '
+    }
+
+    hg_branch() {
+        hg branch 2> /dev/null
+    }
+
+    export PS1='\n\u at \h in \w $(hg_in_repo)$(hg_branch)$(hg_dirty)\n$ '
+
+This gives you a `?` after the branch when there are untracked files (and
+*only* untracked files), and a `!` if there are any modified, tracked files.
+
+Updated: Bookmarks Too!
+----------------
+
+I've added another piece to show bookmarks as well. I've also figured out how
+to add colors directly in the functions, so here's the (much nicer) updated
+code all at once:
+
+    #!bash
+    DEFAULT="[37;40m"
+    PINK="[35;40m"
+    GREEN="[32;40m"
+    ORANGE="[33;40m"
+    
+    hg_dirty() {
+        hg status --no-color 2> /dev/null \
+        | awk '$1 == "?" { unknown = 1 } 
+               $1 != "?" { changed = 1 }
+               END {
+                 if (changed) printf "!"
+                 else if (unknown) printf "?" 
+               }'
+    }
+    
+    hg_branch() {
+        hg branch 2> /dev/null | \
+            awk '{ printf "\033[37;0m on \033[35;40m" $1 }'
+        hg bookmarks 2> /dev/null | \
+            awk '/\*/ { printf "\033[37;0m at \033[33;40m" $2 }'
+    }
+    
+    export PS1='\n\e${PINK}\u \
+    \e${DEFAULT}at \e${ORANGE}\h \
+    \e${DEFAULT}in \e${GREEN}\w\
+    $(hg_branch)\e${GREEN}$(hg_dirty)\
+    \e${DEFAULT}\n$ '
+
+These are some pretty simple changes but they help keep me sane. One thing to
+be aware of: if you use all of these it does slow down the rendering of the
+prompt by a tiny, but noticeable, amount. I'm not the strongest bash scripter,
+so if there's a better way to do this (or a way that will make it faster and
+reduce the delay) please let me know!
+
+**UPDATE:** Matt Kemp posted a link to a [git version][] of this below. If you
+use git, check it out! One thing that version has that I didn't think of is an
+indicator of whether the repository is dirty (has uncommitted changes). I'm
+going to go ahead and steal that idea for my prompt too.
+
+**UPDATE:** By request, I've written [an entry about the
+colors](/blog/entry/2009/3/18/candy-colored-terminal/).
+
+**UPDATE:** Kevin Bullock pointed out that the Python interpreter needed to be
+started a bunch of times which will degrade performance. I've changed up the
+"dirty" code a bit to reduce the number of interpreters needed. It's still not
+as efficient as his version, but I think it's about as good as I'm going to
+get if I want separate colors for the pieces and don't want to rely on an
+external script.
+
+**FINAL UPDATE:** I made an extension for Mercurial called
+[hg-prompt](http://stevelosh.com/projects/hg-prompt/) that does everything
+much more elegantly. **Use that instead!**
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/04/why-people-dont-like-metal.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,130 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Why People Don’t Like Metal"
+    snip: "It’s probably not what you think."
+    created: 2009-04-02 22:32:27
+%}
+
+{% block article %}
+
+I don't think I've ever written a blog entry strictly about music. Usually
+I'll reference it when I write about dancing, but today I just want to talk
+about music. In particular, metal.
+
+"Metal" can refer to a lot of music. For this post I'm referring to the newer
+forms of metal that sprung up in the past decade or so. One example of this is
+[Should Have Stayed in the
+Shallows](http://www.youtube.com/watch?v=hmkLQRp8htY) by [Fear Before (the
+March of Flames)](http://www.fearbefore.net/). I know there are many, many
+more bands out there but this one song is a good sample of what I want to talk
+about.
+
+"I Don't Like all the Screaming"
+------
+
+If you play a metal song for someone that doesn't usually listen to the genre,
+this is probably the first thing you'll hear. There might be a mention of
+"everything is so loud" but almost without fail the screaming is what seems to
+turn people off. Why is that?
+
+The vocals of a song are usually the most noticeable part, especially for
+nonmusicians. Most people who don't play an instrument don't have the
+background to absorb and appreciate complicated instrumental work in any kind
+of music, but *everyone has vocal cords*. Everyone can appreciate speech and
+singing at some level.
+
+So what is it about screaming that most people don't like? If you ask them,
+you'll get an answer, but I don't think it's the correct one.
+
+"I Can't Understand the Words"
+-----
+
+This is what you'll usually hear when you press the issue. It seems reasonable
+-- the lyrics to most metal bands are indecipherable without a written copy,
+even to people that love them. Surely this is the problem?
+
+I don't think it is. To get at the *real* issue, I usually respond with one
+more question:
+
+**Do you enjoy any bands whose vocalist sings in a language you don't know?**
+
+I've never had anyone tell me: "I can't stand *any* music not in my own
+language." I'm sure there are some out there that feel that way, but I think
+they would be in the minority. I've met plenty of people that enjoy hearing
+[Sigur Rós](http://www.sigur-ros.co.uk/) and I'm fairly certain that *exactly
+none of them* speak Icelandic fluently. Many don't even pronounce the name
+correctly.
+
+If people enjoy listening to music with vocals in a language they don't
+understand, then their dislike of metal must not stem purely from
+unintelligible lyrics. What could it come from?
+
+Timbre
+------
+
+Here's one idea: many people are put off by the
+[timbre](http://en.wikipedia.org/wiki/Timbre) of a metal band.
+
+Timbre usually refers to the quality of a musical sound or note. It's what
+makes an E on a guitar sound different than an E on a cello, even if it's the
+same pitch. It's how you can tell your mother's voice from your friend's
+voice, even if she speaks at the same frequency.
+
+A concept I first came across when reading [This Is Your Brain On
+Music](http://www.amazon.com/This-Your-Brain-Music-Obsession/dp/0452288525/)
+is "the timbre of a band as a whole." The idea of timbre can be expanded to
+neatly describe why two bands playing the same song in the same key can sound
+*completely* different. The instruments of the band each contribute their own
+sound and when taken together you have a timbre just as unique as a particular
+instrument's.
+
+Metal bands each have their own timbre, but they're all related -- that's what
+makes them into a genre. A screaming vocalist is an extremely distinct element
+of this that isn't really found anywhere else. Perhaps the answer to "why do
+people dislike metal?" is that they simply don't enjoy the timbre, just as
+some people don't enjoy violins or saxophones.
+
+Lack of Musical Background
+-----
+
+This is another possible answer. As I mentioned before, everyone has vocal
+cords. Everyone can relate to a singer through the words they're singing. Even
+if the words are in a different language they can still relate to the act of
+singing. Not everyone knows how to sing well, but I believe you'd be hard
+pressed to find someone that has never sung in the shower or somewhere just as
+private.
+
+Very few people can (or want to) relate to screaming. Screaming is something
+we usually do only when threatened or angry, which is hopefully a minority of
+our lives. So once the vocalist is screaming constantly, people that don't
+enjoy metal no longer have the element they're most used to focusing on.
+
+What's left? If you can't understand the words, the voice becomes another
+instrument instead of something "special." Many people simply haven't ever
+tried listening to and appreciating purely instrumental music and so they lose
+interest.
+
+What Can We Do?
+-----
+
+I'm sure I haven't completely nailed down the reasons why people don't enjoy
+metal. It's almost certainly a combination of quite a few things. But if
+someone is genuinely interested in learning more about metal and about why
+people like it -- perhaps a close friend listens and they'd like to know more
+-- I think there's two things they can do that may help.
+
+**Think of the vocals as another instrument, and listen to how they interact
+with the rest of the band.**
+
+Admittedly, there's a lot of really terrible metal out there. As the genre has
+expanded in popularity a lot of "musicians" (barely) have jumped in and
+created bands no more musically meaningful than the average pop singer. It's
+easy to come across this and dismiss the whole genre as a bunch of untalented
+hacks.
+
+Word of mouth is probably the best way to pick out the good from the bad. If
+you look hard enough you can find some amazing music that you might grow to
+love and appreciate.
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/05/what-i-hate-about-mercurial.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,228 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "What I Hate About Mercurial"
+    snip: "Hg, I love you, but sometimes you bring me down."
+    created: 2009-05-29 19:51:05
+%}
+
+{% block article %}
+
+This entry was inspired by [Jacob Kaplan-Moss][JKM], who was inspired by
+[Titus][], who was inspired by [brian d foy][BDF]. The premise is that you
+can't really claim to know much about a piece of software until you can name a
+few things you hate about it.
+
+[JKM]: http://jacobian.org/writing/hate-python/
+[Titus]: http://ivory.idyll.org/blog/mar-07/five-things-I-hate-about-python
+[BDF]: http://use.perl.org/~brian_d_foy/journal/32556?from=rss
+
+Jacob and Titus talked about Python, and so have a bunch of other people, so I
+figured I'd write about something a bit different:
+[Mercurial](http://selenic.com/mercurial).
+
+I love Mercurial to death, but there *are* a few things about it that annoy
+me. Here they are, in no particular order.
+
+[TOC]
+
+Configuration Through a Textfile
+--------------------------------
+
+This is one of the things that [git](http://git-scm.com/) people seem to like
+to [bring up](http://jointheconversation.org/2008/11/24/on-mercurial.html):
+"It doesn't have a command to set your username and email and such? Lame."
+
+I personally don't mind editing a text file -- `vim ~/.hgrc` really isn't that
+hard to type and the format is simple enough that you get the hang of it in
+about ten seconds. It forces you to know *where* the config file is, which is
+nice when the magic "Oh man, I could put my config files under *version
+control*!" moment strikes.
+
+That said, this is on the list because I'd like to see a command to edit some
+of the common options just so people will *stop complaining* about something
+so trivial.
+
+"hg rm" is a Confusing Mess
+---------------------------
+
+Here's part of the help for the `hg rm` command:
+
+> This only removes files from the current branch, not from the entire
+> project history. -A can be used to remove only files that have already
+> been deleted, -f can be used to force deletion, and -Af can be used
+> to remove files from the next revision without deleting them.
+
+What the hell? If `-A` won't remove files that are still present, and `-f`
+forces the files to be deleted, why the fuck does combining them mean *the
+exact opposite of both*?
+
+I had to look up the syntax every single time I wanted to use this command,
+until I added this alias to my `~/.hgrc`:
+
+    [alias]
+    untrack = rm -Af
+
+Now I can use `hg untrack whatever.py` to stop tracking a file.
+
+Addremove Can Track Renames But Won't Unless You Ask It Really Nicely
+---------------------------------------------------------------------
+
+It took me a while to realize this, but Mercurial can actually record file
+renames -- not just separate adds and removes -- when using `hg addremove`.
+Here's what happens when you move a file and then use `hg addremove` normally
+to have Mercurial track the changes.
+
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ ls
+    total 16
+    -rw-r--r--  1 sjl    14B May 29 20:12 a
+    -rw-r--r--  1 sjl    12B May 29 20:12 b
+    
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ mv b c
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg addremove
+    removing b
+    adding c
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg diff
+    diff --git a/b b/b
+    deleted file mode 100644
+    --- a/b
+    +++ /dev/null
+    @@ -1,1 +0,0 @@
+    -To you too!
+    diff --git a/c b/c
+    new file mode 100644
+    --- /dev/null
+    +++ b/c
+    @@ -0,0 +1,1 @@
+    +To you too!
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg commit -m 'Normal addremove.'
+    
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ 
+
+Now watch what happens when we tell Mercurial to detect renames when using `hg
+addremove`:
+
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ ls
+    total 16
+    -rw-r--r--  1 sjl    14B May 29 20:12 a
+    -rw-r--r--  1 sjl    12B May 29 20:12 c
+    
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ mv c b
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg addremove --similarity 100
+    adding b
+    removing c
+    recording removal of c as rename to b (100% similar)
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg diff
+    diff --git a/c b/b
+    rename from c
+    rename to b
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg commit -m 'This time with rename detection.'
+    
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ 
+
+This time it notices the rename, and records it. The diff is far, far easier
+to read, and if a branch is merged in where someone else changed that file,
+the changes will follow it over.
+
+The `--similarity` option is a percentage. I have an entry in my `~/.hgrc`
+file to default that to 100, which means that renames will only be
+automatically detected if the files are *identical*. It's safer, but might not
+always catch everything.
+
+I wish I had known this earlier or that Mercurial defaulted to 100% to catch
+the obvious renames.
+
+And yes, I realize I could use `hg rename` to rename it and it *would* get
+recorded, but usually I'm moving files by some other method and using `hg
+addremove` to clean up later.
+
+Now, while we're on the topic...
+
+Why the Hell Does Status Not Show Renames?
+------------------------------------------
+
+Assuming they're recorded, I wish `hg status` would show that a file has been
+renamed. Here's what we get instead:
+
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ hg rename b c
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg stat
+    A c
+    R b
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg diff
+    diff --git a/b b/c
+    rename from b
+    rename to c
+
+No, `hg status`, it clearly *wasn't* an add and a remove, according to `hg
+diff`. Why doesn't `hg status` have a separate character for "renamed" files
+so we can tell them apart?
+
+Get Git Out of My Mercurial
+---------------------------
+
+I *hate* that half of Mercurial's commands need a `--git` option to be really
+useful. Is there any reason not to make this the default format and have a
+`--useless` option for backwards compatibility?
+
+I always add it to the defaults in my `~/.hgrc` but it makes me feel kind of
+dirty when I do. It adds a bunch of unnecessary lines to the config file and
+confuses new people.
+
+BitBucket Could Be Prettier
+---------------------------
+
+Don't get me wrong, [BitBucket](http://bitbucket.org/) is an awesome site, but
+compared to [GitHub](http://github.com/) it looks a bit dull and unappealing.
+
+It's definitely more usable (how the hell do I view a graph of all
+branches/merges of a given repository on GitHub?) but there's something about
+GitHub's design that just makes it pop.
+
+Mercurial's Site Could Be *Much* Prettier
+-----------------------------------------
+
+Mercurial's site is ugly. Very ugly. It seems strange to me that the ugly
+version control system (git) has a fairly good-looking site while the much
+more elegant Mercurial has something that looks so boring and dated.
+
+I know, [mercurial-scm.org](http://mercurial-scm.org/) aims to fix this. Thank
+you from the bottom of my heart but please, hurry. The wiki is hurting my
+eyes.
+
+But Hey, at Least It's Not Git!
+--------------------------------
+
+All of those things annoy me, but they're small problems compared to the
+revulsion I get when I try to use git every so often.
+
+Maybe that would be a good topic for another entry. At the very least it'll
+probably get me a ton of pageviews and comments saying: "Git's changed, man!
+It's not like it used to be, it's totally intuitive now! You just gotta learn
+how it stores the data!"
+
+I learned, and I'll still take Mercurial despite the small annoyances.
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/06/how-to-contribute-to-mercurial.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,367 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "How to Contribute to Mercurial"
+    snip: "Ten minutes of setup will make it easier."
+    created: 2009-06-01 20:09:44
+%}
+
+{% block article %}
+
+After my last post on [What I Hate About Mercurial][hate], seydar commented
+that I should contribute a patch to add untrack/forget functionality. I
+decided to take the advice, stop being lazy and write one.
+
+It's a very, very simple change and I'm not sure if it will even make it into
+the core repository, but even so it gave me a chance to figure out how to set
+up a decent development environment for hacking on Mercurial. I figured that
+other people might find that information useful so I decided to write this.
+
+[hate]: http://stevelosh.com/blog/entry/2009/5/29/what-i-hate-about-mercurial/
+
+[TOC]
+
+About This Guide
+----------------
+
+This is meant to be a guide to get yourself set up to work on Mercurial's code
+base and contribute your work back to the community. It's *not* a guide for
+actually working on the code.
+
+I'm going to go ahead and assume a few (small) things:
+
+1. You're running OS X or some form of Linux.  If you're using Windows, I'm sorry, but I just don't use it enough to really help.
+2. You've got [Python][] installed.
+3. You've got a copy of Mercurial installed in some way (MacPorts, apt-get, source, etc).
+4. You're familiar with (and have clients for) IRC and email.
+
+If those things are true, let's get started. The entire process should take
+between 15 and 45 minutes, depending on how comfortable you are with bash,
+Python, and Mercurial itself.
+
+[Python]: http://python.org/
+
+Join the Community
+------------------
+
+The first step to contributing is to join the community. Things will probably
+go more smoothly if other developers have seen your name before and those
+other developers are a great resource if you get stuck.
+
+Join the [#mercurial channel on Freenode][irc]. A lot of other Mercurial
+developers hang out in there and it's a good place to go if you want some
+really quick feedback. Take a few minutes and [register your nick][register]
+on Freenode, just because it's a good thing to do.
+
+You should also [subscribe][] to the Mercurial development [mailing list][].
+That's where you're going to be sending your work, so it's good to start
+getting an idea of how people use the list as soon as possible.
+
+[irc]: irc://irc.freenode.net/#mercurial
+[register]: http://freenode.net/faq.shtml#userregistration
+[subscribe]: http://www.selenic.com/mailman/listinfo/mercurial-devel/
+[mailing list]: http://www.selenic.com/pipermail/mercurial-devel/
+
+Grab the Source
+---------------
+
+Now you'll want to grab the Mercurial source code so you can start changing
+it. The repository you almost certainly want to clone is the [crew
+repository][].
+
+Several people (listed [here][crew members]) have write access to this and
+it's where most changes go before they're pulled into the main Mercurial
+repositories. Your want your changes to apply cleanly to the tip of crew if
+you want them to have the best chance of being accepted.
+
+Go ahead and clone it somewhere on your machine (replace `hg-crew` if you
+prefer a different name for the folder):
+
+    hg clone http://hg.intevation.org/mercurial/crew hg-crew
+
+It's going to take a little while. Mercurial might be fast but its repository
+has over 8,600 changesets. While you're waiting you can move on to the next
+step.
+
+[crew repository]: http://hg.intevation.org/mercurial/crew
+[crew members]: http://www.selenic.com/mercurial/wiki/CrewRepository
+
+Set Up virtualenv
+-----------------
+
+This might not seem like it's necessary, but trust me, it's a good thing to
+do. It will make things easier down the road, I promise.
+
+No, *really*, take ten minutes and do this. You'll thank me.
+
+[virtualenv][] is a tool that lets you create separate Python development
+environments that are isolated from each other. The packages and binaries for
+one won't contaminate the others. It will make testing our work on Mercurial
+painless.
+
+Open a new terminal window while the crew repository is busy cloning. Install
+virtualenv in the usual Python fashion:
+
+    sudo easy_install virtualenv
+
+Now install the [virtualenvwrapper][] tool:
+
+    sudo easy_install virtualenvwrapper
+
+This is a nifty little shell script that makes working with virtual
+environments much more pleasant. Before you can use it, you'll need to source
+it into your `~/.bashrc` or `~/.bash_profile` file, as well as choose a place
+to stick the environments themselves:
+
+    export WORKON_HOME=$HOME/lib/virtualenvs
+    source /(path to python)/bin/virtualenvwrapper_bashrc
+
+As you can see, I prefer to put the `virtualenvs` folder inside my `~/lib`
+folder. You can change that to any place you like.
+
+You'll also need to replace the `(path to python)` with the actual path to
+wherever Python is installed on your system. If you're not sure, here's a
+simple, slow, and horribly inefficient but effective command to figure it out:
+
+    find / -name 'virtualenvwrapper_bashrc' 2> /dev/null
+
+Once you've got the necessary lines in your `~/.bashrc` you can close that
+terminal window.
+
+[virtualenv]: http://pypi.python.org/pypi/virtualenv
+[virtualenvwrapper]: http://www.doughellmann.com/projects/virtualenvwrapper/
+
+Set Up A Public Repository
+--------------------------
+
+This isn't strictly required, but it's polite and only takes a minute or two.
+If you've already got a method of sharing your repositories (using hgwebdir
+with your website, for example) go ahead and use that.
+
+If not, head over to [BitBucket][], sign up for an account if you don't
+already have one (it's free), and create a new public repository there. I've
+named mine [hg-crew-sjl][] to be explicit about what it contains, but that's
+not terribly important.
+
+Why bother doing this when you're just going to email your work anyway? Some
+people (myself included) find it easier to pull changes from another
+repository than to apply them from emails. It also gets your changes out into
+a public place so other developers can view and modify *your* modifications.
+
+It's also nice to have an easily accessible clone of your personal repository
+if you're not at your own machine and want to do some more work.
+
+[BitBucket]: http://bitbucket.org/
+[hg-crew-sjl]: http://bitbucket.org/sjl/hg-crew-sjl/
+
+Set Up Your Local Clone
+-----------------------
+
+By now the crew repository should be finished cloning to your local machine.
+The first thing we want to do is set up the paths so we can push and pull
+easily. Modify the `.hg/hgrc` file inside that repository (*not* your
+`~/.hgrc` file!) to look like this:
+
+    [paths]
+    default = http://bitbucket.org/(username)/(repo name)/
+    crew = http://hg.intevation.org/mercurial/crew
+
+Replace `(username)` with your BitBucket username and `(repo name)` with the
+name of the BitBucket repository, obviously.
+
+Now you can run `hg push` to push any changes you commit locally to your
+public BitBucket repository, and `hg pull crew` to grab new changes from the
+crew repository.
+
+Build Mercurial
+---------------
+
+Make sure you're in your local crew repository, and run:
+
+    make local
+
+This will build Mercurial from the source files. It should finish fairly
+quickly. Once that's done, run the tests to make sure everything is working
+correctly:
+
+    make tests
+
+Those will take a long time to run. While you wait, move on to the next step.
+
+Create a Virtual Environment for Mercurial Development
+------------------------------------------------------
+
+While the test suite is running you're going to make a new virtual environment
+to use for testing your changes to Mercurial. First you need to create it, so
+open up a new terminal window and run:
+
+    mkvirtualenv hg-dev
+
+You can name it something else if you don't like `hg-dev`. Notice how your
+shell prompt now has `(hg-dev)` prepended to it? That's there to remind you
+that you're working in that environment.
+
+Creating the environment automatically puts you into it for that shell
+session. To get into it in the future you'll use:
+
+    workon hg-dev
+
+Now you need to link the Mercurial libraries you're going to change to this
+environment, so you can use it to test your code. Run the following three
+commands:
+
+    ln -s (full path to crew)/mercurial $WORKON_HOME/hg-dev/lib/python2.6/site-packages/
+    ln -s (full path to crew)/hgext $WORKON_HOME/hg-dev/lib/python2.6/site-packages/
+    ln -s (full path to crew)/hg $WORKON_HOME/hg-dev/bin/
+
+Replace `(full path to crew)` with the *full* path to your local crew
+repository, and `hg-dev` with the name of your virtual environment (if you
+named it differently than I did).
+
+Why Bother With a Virtual Environment?
+--------------------------------------
+
+It's probably the most work in this entire process, so why did I insist you
+set it up? Watch this:
+
+    :::console
+    sjl at ecgtheow in ~/src/hg-crew-sjl on default 
+    $ hg --version
+    Mercurial Distributed SCM (version 1.2.1)
+    
+    Copyright (C) 2005-2009 Matt Mackall <mpm@selenic.com> and others
+    This is free software; see the source for copying conditions. There is NO
+    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+    
+    sjl at ecgtheow in ~/src/hg-crew-sjl on default 
+    $ workon hg-dev
+    
+    (hg-dev)
+    sjl at ecgtheow in ~/src/hg-crew-sjl on default 
+    $ hg --version
+    Mercurial Distributed SCM (version 7956a823daa3)
+    
+    Copyright (C) 2005-2009 Matt Mackall <mpm@selenic.com> and others
+    This is free software; see the source for copying conditions. There is NO
+    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+    
+    (hg-dev)
+    sjl at ecgtheow in ~/src/hg-crew-sjl on default 
+    $ 
+
+Look at the version numbers. Notice how they changed?
+
+**You can now use** `workon hg-dev` **to make the** `hg` **command run
+Mercurial with your changes!**
+
+This makes it simple to test your work as you go. I keep two terminal windows
+open while working on the Mercurial source:
+
+* One is in my local crew repository to diff, commit, etc with the standard version of Mercurial.
+* The other is in a test repository.  I've run `workon hg-dev` to switch to my modified version so I can try out my changes.
+
+Get To Work!
+------------
+
+That's it for the initial setup. Now you can start adding all the wonderful
+features you have in mind. A simple workflow might go something like this:
+
+1. Open two terminal windows and use `workon hg-dev` in the second one to switch to the virtual environment.
+2. Make some changes to the Mercurial codebase.
+3. Test your changes in the second terminal window.
+4. Repeat 3 and 4, using the first terminal window to commit to the local repository as you go.
+
+Once you're finished with your shiny new feature, how do you get it into the
+main Mercurial code so we can all benefit from it?
+
+Modify the Test Suite
+---------------------
+
+Before you go off and submit a patch, you need to make sure it works with the
+current tests. You can run the tests by going to the repository and using:
+
+    cd tests
+    python run-tests.py
+
+It's going to take a while, just like before. If you changed something that
+modifies the output of a command it will probably break some of the existing
+tests. That's alright, but you'll need to fix them to reflect your changes.
+The simplest way to do this is to use the `--interactive` flag:
+
+    python run-tests.py --interactive
+
+Using `--interactive` will prompt you each time a test fails and ask if you
+want to accept the new output as the "correct" output. This makes it simple to
+update the existing tests to take your changes into account.
+
+Obviously you should **only accept these updates if they make sense**. Pay
+attention to the output and make sure you didn't accidentally break something!
+
+Add to the Test Suite
+----------------------
+
+If you've implemented an entirely new feature (as opposed to just modifying an
+existing one) you should add some tests of your own. This will make sure no
+one else will inadvertently break whatever you've added.
+
+There's a nice [guide][test-guide] to this on the Mercurial site. Follow it to
+add some tests for your changes.
+
+From what I've heard it's preferable to append to an existing set of tests (if
+it makes sense) instead of adding a brand new test file -- the tests run
+pretty slowly and adding new files make them even slower.
+
+[test-guide]: http://www.selenic.com/mercurial/wiki/WritingTests#Writing_a_shell_script_test
+
+Email Your Patches to the Mailing List
+--------------------------------------
+
+You've finally got your code working and updated the tests. It's time to share
+your changes with the rest of the Mercurial developers.
+
+If you want your patches to get accepted, you should take the time to read the
+[guide to contributing changes][] and the [guide to making successful
+patches][] on the Mercurial site. They're short but contain most of what you
+need to know.
+
+[guide to contributing changes]: http://www.selenic.com/mercurial/wiki/ContributingChanges
+[guide to making successful patches]: http://www.selenic.com/mercurial/wiki/SuccessfulPatch
+
+I prefer to use the [patchbomb][] extension to email the patches because it
+takes care of the formatting for me. To enable and configure it you'll need to
+make some additions to your `~/.hgrc` file:
+
+    :::text [extensions] hgext.patchbomb =
+    
+     [email] method = smtp from = Your Name <you@yourdomain.com>
+    
+     [smtp] host = smtp.youremailhost.com username = yourusername tls = True
+    
+    You'll need to tweak those settings with your own email address, mail
+    server, and so on. Once that's done, you can have patchbomb package up
+    your changes and email them out:
+
+    hg email --rev (your first revision):(your last revision)
+
+The command will guide you through filling out some more information, and then
+send out the patches. `hg help email` has a lot more information on how to use
+it.
+
+I usually email them to myself first just in case I mess up a revision number
+and email six thousand changesets. Flooding my own inbox is much better than
+flooding the list's.
+
+[patchbomb]: http://www.selenic.com/mercurial/wiki/PatchbombExtension
+
+That's It, Now Go Contribute!
+-----------------------------
+
+That's about the extent of my knowledge on contributing to Mercurial. As I
+said before, I've only done one patch so far, but I wanted to write this while
+everything about setting up the environment was fresh in my mind.
+
+If any of the other Mercurial developers would like to chime in and suggest
+corrections or additions -- or if anyone has any questions -- I'll be happy to
+update the post. I hope it's helpful!
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/08/a-guide-to-branching-in-mercurial.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,399 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "A Guide to Branching in Mercurial"
+    snip: "With illustrations and comparisons to git."
+    created: 2009-08-30 20:27:12
+%}
+
+{% block article %}
+
+<div class="with-diagrams">
+
+I've been hanging out in the [#mercurial][hg-irc] and [#bitbucket][bb-irc]
+channels on freenode a lot lately, and I've noticed a topic that comes up a
+lot is "how does [Mercurial][hg]'s branching differ from [git][]'s branching?"
+
+[hg]: http://mercurial.selenic.com/
+[git]: http://git-scm.com/
+[hg-irc]: irc://irc.freenode.net/#mercurial
+[bb-irc]: irc://irc.freenode.net/#bitbucket
+[freenode]: http://freenode.net/
+
+A while ago [Nick Quaranto][nick] and I were talking about Mercurial and git's
+branching models on Twitter and I wrote out a [quick longreply][lreply] about
+the main differences. Since then I've pointed some git users toward that post
+and they seemed to like it, so I figured I'd turn it into something a bit more
+detailed.
+
+**Disclaimer:** this post is not intended to be a guide to the commands used
+for working with Mercurial. It is only meant to be a guide to the *concepts*
+behind the branching models. For more information on daily use and commands,
+the [hg book][book] is a great resource (if you find it useful, please
+[buy][book-buy] a paper copy to support Bryan and have a printed copy of the
+[best editing fail of all time][editfail]).
+
+[nick]: http://litanyagainstfear.com/
+[lreply]: http://a.longreply.com/178502
+[book]: http://hgbook.red-bean.com/
+[book-buy]: http://search.barnesandnoble.com/Mercurial/Bryan-OSullivan/e/9780596800673/?itm=1
+[editfail]: http://twitpic.com/cwod4
+
+[TOC]
+
+Prologue
+--------
+
+Before I start explaining the different branching models, here's a simple
+repository I'll use as an example:
+
+![Basic Repository Diagram](/media/images{{ parent_url }}/branch-base.png "Basic Repository")
+
+The repository is in the `~/src/test-project` folder. It has three changesets
+in it: numbers 0, 1 and 2.
+
+**For git users:** each changeset in a Mercurial repository has a hash as an
+identifier, just like with git. However, Mercurial also assigns numbers to
+each changeset in a repository. The numbers are *only* for that local
+repository -- two clones might have different numbers assigned to different
+changesets depending on the order of pulls/pushes/etc. They're just there for
+convenience while you're working with a repository.
+
+The default branch name in Mercurial is "default". Don't worry about what that
+means for now, we'll get to it. I'm mentioning it because there's a little
+`default` marker in the diagram.
+
+In all of these diagrams, a marker like that with a dashed border doesn't
+actually exist as an object anywhere. Those are special names that you can use
+to identify a changeset instead of the hash or number -- Mercurial will
+calculate the revision on the fly.
+
+For now, ignore the `default` marker. I've colored it grey in each of the
+diagrams where it doesn't matter.
+
+Branching with Clones
+---------------------
+
+The slowest, safest way to create a branch with Mercurial is to make a new
+clone of the repository:
+
+    $ cd ~/src
+    $ hg clone test-project test-project-feature-branch 
+
+Now you've got two copies of the repository. You can commit separately in each
+one and push/pull changesets between them as often as you like. Once you've
+made some changes in each one, the result might look like this:
+
+![Clone Diagram](/media/images{{ parent_url }}/branch-clone.png "Branching with Clones")
+
+We've got two copies of the repository. Both contain the changesets that
+existed at the time we branched/cloned. If we push from `test-project` into
+`test-project-feature-branch` the "Fix a critical bug" changeset will be
+pushed over.
+
+**For git users:** Remember how I mentioned that the changeset numbers are
+local to a repository? We can see this clearly here -- there are two different
+changesets with the number 3. The numbers are *only* used while working inside
+a single repository. For pushing, pulling, or talking to other people you
+should use the hashes.
+
+### Advantages
+
+Cloning is a very safe way of creating a branch. The two repositories are
+completely isolated until you push or pull, so there's no danger of breaking
+anything in one branch when you're working in another.
+
+Discarding a branch you don't want any more is *very* easy with cloned
+branches. It's as simple as `rm -rf test-project-feature-branch`. There's no
+need to mess around with editing repository history, you just delete the damn
+thing.
+
+### Disadvantages
+
+Creating a branch by cloning locally is slower than the other methods, though
+Mercurial will use hardlinks when cloning if your OS supports them (most do)
+so it won't be *too* slow.
+
+However, the clone branching method can really slow things down when other
+developers (not located nearby) want to work on the project. If you publish
+two branches as separate repositories (such as `stable` and `version-2`),
+contributors will have to clone down *both* repositories through the internet
+if they want to work on both branches. That can take a lot of extra time,
+depending on the repository size and bandwidth.
+
+It can become especially wasteful if, for example, there are 10,000 changesets
+before the branch point and maybe 100 per branch after. Instead of pulling
+down 10,200 changesets you need to pull down 20,200. If you want to work on
+three different branches, you're pulling down 30,300 instead of 10,300.
+
+There is a way to avoid this large download cost, as pointed out by Guido
+Ostkamp and timeless_mbp in [#mercurial][hg-irc]. The idea is that you clone
+one branch down from the server, then pull *all* the branches into it, then
+clone locally to split that repository back into branches. This avoids the
+cost of cloning down the same changesets over and over.
+
+An example of this method with three branches would look something like this:
+
+    $ hg clone http://server/project-main project
+    $ cd project
+    $ hg pull http://server/project-branch1
+    $ hg pull http://server/project-branch2
+    $ cd ..
+    $ hg clone project project-main --rev [head of mainline branch]
+    $ hg clone project project-branch1 --rev [head of branch1]
+    $ hg clone project project-branch2 --rev [head of branch2]
+    $ rm -rf project
+    $ cd project-main
+    $ [edit .hg/hgrc file to make the default path http://server/project-main]
+    $ cd ../project-branch1
+    $ [edit .hg/hgrc to make the default path http://server/project-branch1]
+    $ cd ../project-branch2
+    $ [edit .hg/hgrc to make the default path http://server/project-branch2]
+
+This example assumes you know the IDs of the branch heads off the top of your
+head, which you probably don't. You'll have to look them up.
+
+It also assumes that there is only one new head per branch, when there might
+be more. If `branch1` has two heads which are not in `mainline`, you would
+need to look up the IDs of *both* and specify both in the clone command.
+
+Another annoyance shows up when you're working on a project that relies on
+your code being at a specific file path. If you branch by cloning you'll need
+to rename directories (or change the file path configuration) every time you
+want to switch branches. This might not be a common situation (most build
+tools don't care about the absolute path to the code) but it *does* appear now
+and then.
+
+I personally don't like this method and don't use it. Others do though, so
+it's good to understand it (Mercurial itself uses this model).
+
+### Comparison to git
+
+Git can use this method of branching too, although I don't see it very often.
+Technically this is the exact same thing as creating a fork on [GitHub][], but
+most people think of "fork" and "branch" as separate concepts.
+
+[GitHub]: http://github.com/
+
+Branching with Bookmarks
+------------------------
+
+The next way to branch is to use a bookmark.  For example:
+
+    $ cd ~/src/test-project
+    $ hg bookmark main
+    $ hg bookmark feature
+
+[bookmark]: http://mercurial.selenic.com/wiki/BookmarksExtension
+
+Now you've got two bookmarks (essentially a tag) for your two branches at the
+current changeset.
+
+To switch to one of these branches you can use `hg update feature` to update
+to the tip changeset of that branch and mark yourself as working on that
+branch. When you commit, it will move the bookmark to the newly created
+changeset.
+
+**Note:** for more detailed information on actually using bookmarks day-to-day
+please read the [bookmarks page][bookmark]. This guide is meant to show the
+different branching models, and bookmarks have a few quirks that you should
+know about if you're going to use them.
+
+Here's what the repository would look like with this method:
+
+![Bookmark Diagram](/media/images{{ parent_url }}/branch-bookmark.png "Branching with Bookmarks")
+
+The diagram of the changesets is pretty simple: the branch point was at
+changeset 2 and each branch has one new changeset on it.
+
+Now let's look at the markers. The `default` marker is still there, and we're
+still going to ignore it.
+
+There are two new labels in this diagram -- these represent the bookmarks.
+Notice how their outlines are *not* dashed? This is because bookmarks are
+actual objects stored on disk, not just convenient shortcuts that Mercurial
+will let you use.
+
+When you use a bookmark name as a revision Mercurial will look up the revision
+it points at and use that.
+
+### Advantages
+
+Bookmarks give you a quick, lightweight way to give meaningful label your
+branches.
+
+You can delete them when you no longer need them. For example, if we finish
+development of the new feature and merge the changes in the main branch, we
+probably don't need to keep the `feature` bookmark around any more.
+
+### Disadvantages
+
+Being lightweight can also be a disadvantage. If you delete a bookmark, then
+look at your code a year later and wonder what all those changesets that got
+merged into main were for, the bookmark name is gone. This probably isn't a
+big issue if you write good changeset summaries.
+
+Bookmarks are local. They do *not* get transferred during a push or pull!
+There has been some whispering about adding this is Mercurial 1.4, but for now
+if you want to give someone else your bookmarks you'll need to manually give
+them the file the bookmarks are kept in.
+
+### Comparison to git
+
+Branching with bookmarks is very close to the way git usually handles
+branching. Mercurial bookmarks are like git refs: named pointers to changesets
+that move on commit.
+
+The biggest difference is that git refs are transferred when pushing/pulling
+and Mercurial bookmarks are not.
+
+Branching with Named Branches
+-----------------------------
+
+The third way of branching is to use Mercurial's named branches. Some people
+prefer this method (myself included) and many others don't.
+
+To create a new named branch:
+
+    $ cd ~/src/test-project
+    $ hg branch feature
+
+When you commit the newly created changeset will be on the same branch as its
+parent, unless you've used `hg branch` to mark it as being on a different one.
+
+Here's what a repository using named branches might look like:
+
+![Named Branch Diagram](/media/images{{ parent_url }}/branch-named.png "Branching with Named Branches")
+
+An important difference with this method is that the branch name is
+permanently recorded as part of the changeset's metadata (as you can see in
+changeset 4 in the diagram).
+
+**Note:** The default branch is called `default` and is not normally shown
+unless you ask for verbose output.
+
+Now it's time to explain those magic dashed-border labels we've been ignoring.
+Using a branch name to specify a revision is shorthand for "the tip changeset
+of this named branch". In this example repository:
+
+* Running `hg update default` would update to changeset 3, which is the tip of the `default` branch.
+* Running `hg update feature` would update to changeset 4, which is the tip of the `feature` branch.
+
+Neither of these labels actually exist as an object anywhere on disk (like a
+bookmark would). When you use them Mercurial calculates the appropriate
+revision on the fly.
+
+### Advantages
+
+The biggest advantage to using named branches is that every changeset on a
+branch has the branch name as part of its metadata, which I find very helpful
+(especially when using [graphlog][]).
+
+[graphlog]: http://mercurial.selenic.com/wiki/GraphlogExtension
+
+### Disadvantages
+
+Many people don't like cluttering up changeset metadata with branch names,
+especially if they're small branches that are going to be merged pretty
+quickly.
+
+In the past there was also the problem of not having a way to "close" a
+branch, which means that over time the list of branches could get huge. This
+was fixed in Mercurial 1.2 which introduced the `--close-branch` option for
+`hg commit`.
+
+### Comparison to git
+
+As far as I know git has no equivalent to Mercurial's named branches. Branch
+information is never stored as part of a git changeset's metadata.
+
+Branching Anonymously
+---------------------
+
+The last method of branching with Mercurial is the fastest and easiest: update
+to any revision you want and commit. You don't have to think up a name for it
+or do anything else -- just update and commit.
+
+When you update to a specific revision, Mercurial will mark the parent of the
+working directory as that changeset. When you commit, the newly created
+changeset's parent will be the parent of the working directory.
+
+The result of updating and committing without doing anything else would be:
+
+![Anonymous Diagram](/media/images{{ parent_url }}/branch-anon.png "Branching Anonymously")
+
+How do you switch back and forth between branches once you do this? Just use
+`hg update --check REV` with the revision number (or hash) (you can shorten
+`--check` to `-c`).
+
+**Note:** the `--check` option was added in Mercurial 1.3, but it was broken.
+It's fixed in 1.3.1. If you're using something earlier than 1.3.1, you really
+should update.
+
+Logging commands like `hg log` and `hg graphlog` will show you all the
+changesets in the repository, so there's no danger of "losing" changesets.
+
+### Advantages
+
+This is the fastest, easiest way to branch. You don't have to think of a name
+or close/delete anything when you're finished -- just update and commit.
+
+This method is *great* for quick-fix, two-or-three-changeset branches.
+
+### Disadvantages
+
+Using anonymous branching obviously means that there won't be any descriptive
+name for a branch, so you'll need to write good commit messages if you want to
+remember what a branch was for a couple of months later.
+
+Not having a single name to represent a branch means that you'll need to look
+up the revision numbers or hashes with `hg log` or `hg graphlog` each time you
+want to switch back and forth. If you're switching a lot this might be more
+trouble than it's worth.
+
+### Comparison to git
+
+Git has no real way to handle this. Sure, it lets you update and commit, but
+if you don't create a (named) ref to that new commit you're never going to
+find it again once you switch to another one. Well, unless you feel like
+grep'ing through a bunch of log output.
+
+Oh, and hopefully it doesn't get garbage collected.
+
+Sometimes you might not want to think up a name for a quick-fix branch. With
+git you *have* to name it if you want to really do anything with it, with
+Mercurial you don't.
+
+One More Difference Between Mercurial and git
+---------------------------------------------
+
+There's one more *big* difference between Mercurial's branching and git's
+branching:
+
+**Mercurial will push/pull *all* branches by default, while git will push/pull
+only the *current* branch.**
+
+This is important if you're a git user working with Mercurial. If you want to
+push/pull only a single branch with Mercurial you can use the `--rev` option
+(`-r` for short) and specify the tip revision of the branch:
+
+    $ hg push --rev branchname
+    $ hg push --rev bookmarkname
+    $ hg push --rev 4
+
+If you specify a revision, Mercurial will push that changeset and any
+ancestors of it that the target doesn't already have.
+
+This doesn't apply when you use the "Branching with Clones" method because the
+branches are separate repositories.
+
+Conclusion
+----------
+
+I hope this guide is helpful. If you see anything I've missed, especially on
+the git side of things (I don't use git any more than I have to) or have any
+questions please let me know!
+
+</div>
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/11/my-sitesprint-project-lindyhub.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,196 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "My SiteSprint Project: LindyHub"
+    snip: "I want to make something awesome for dancers."
+    created: 2009-11-16 19:15:07
+%}
+
+{% block article %}
+
+If you're a web designer and/or developer, you might have heard of
+[SiteSprint][]. From the SiteSprint page:
+
+>What is the Site Sprint?  
+>A challenge to do something about our personal websites. If you were looking 
+>for a reason to rework an existing site or launch a new one, here it is.
+
+The event has a couple of rules:
+
+>The Rules  
+>1. Launch by 12/15  
+>2. Document your process  
+>3. On launch, share what you did and how you did it
+
+I've decided to join in and finish up a pet project of mine that I've been
+working on (very sporadically) for the past six months or so: [LindyHub][]
+
+[SiteSprint]: http://sitesprint.info/
+[LindyHub]: http://lindyhub.com/
+
+[TOC]
+
+Preface: About Swing Dancing
+----------------------------
+
+If you're a dancer, go ahead and skip to the next section. This is for the
+programmers and designers that might not have heard of Lindy Hop.
+
+[Lindy Hop][] is a form of swing dancing. I've been doing it for six years and
+love it.
+
+Part of the Lindy Hop culture consists of "exchanges" and "workshop weekends".
+The general idea is that a group of dancers will host one of these events on a
+weekend. They'll hire DJs or bands, and teachers if they're going to have
+classes, and plan out a whole weekend of awesomeness.
+
+Dancers from far and wide will travel to these events to meet and dance with
+new people (and old friends).
+
+If you want more background on dancing post a comment and I'll gladly explain
+more, but this in-a-nutshell explanation should be enough for you to
+understand the rest of this entry.
+
+[Lindy Hop]: http://en.wikipedia.org/wiki/Lindy_hop
+
+The Problem
+-----------
+
+LindyHub is a project I've been working on for about six months off and on in
+my spare time and it was rolling around in my head before that.
+
+Over the last few years or so I've been getting back into web development and
+design. At the beginning of this year I started to notice a trend: most
+websites for Lindy Hop and blues events are very basic and unpolished. Some of
+the things I've noticed about almost every event site:
+
+* They have a form for you to register for the event, but the form almost never has any nice inline validation of your input.
+* Every site's form is different -- you have to read every single one carefully to see exactly what they want.
+* You end up entering the same information every single time for every event: name, phone number, email, etc.
+* Housing is a toss up.  Sometimes they have a place for it in the registration form, other times they just say "Email aaa@bbb.com if you need housing."  That's a lot of emails for the housing coordinator to sort through and quite often it can become a mess.
+* Some of them list addresses for each venue, which is great for those of us that have GPSes.  Sometimes they just give driving directions to and from each one, which is terrible if you just want to type each one into your GPS or print off directions from Google Maps before you go.
+* Only one event that I've gone to ([Blues Muse][] in Philly) has had a "Who's Coming" list so you could see who else was going to the event (you could choose whether or not to let them show your name when you registered). Sometimes you can figure this out from Facebook event pages, but that's pretty unreliable.
+
+There are other things, but those are the big ones.
+
+Now, I completely understand why people don't add those features to their
+event sites. It doesn't make sense to spend 10 hours adding cool features that
+are nice to have but not really necessary if your website is only going to be
+used for a single event. Those 10 hours could be spent promoting your event
+and getting more people to come which is better for everyone.
+
+Around the time I was noticing these things I was also starting to get back
+into contributing to open source projects. Two of the big project hosting
+sites nowadays are [BitBucket][] and [GitHub][]. I noticed how they both make
+starting a new project almost trivially easy -- you sign up for an account and
+within two minutes people can view and contribute back to your new project.
+They've fostered a lot of collaboration in the open source community and it's
+been a very good thing all around.
+
+The two ideas came together in my head pretty quickly. I started thinking
+about designing a site that made setting up a dance event almost as easy as
+forking a project on BitBucket.
+
+Sure, every organizer spending 10 hours to add cool features to their event
+site doesn't really make sense. But what if one person spent a couple hundred
+hours and built a site that let every organizer add those features in 10
+*minutes*? After 20 or 30 events it's saved those couple hundred hours and
+just gets better from there.
+
+The more I thought about it the more it seemed like a good idea. I'd been
+learning a lot about web development and about six months ago I decided I was
+competent enough to handle something like this, and started working on the
+LindyHub core.
+
+[Blues Muse]: http://www.lindyandblues.com/events/2009/bluesmuse/
+[BitBucket]: http://bitbucket.org/
+[GitHub]: http://github.com/
+
+LindyHub's Current State
+------------------------
+
+I've been working on LindyHub off and on for the past six months or so, and it
+has been coming along pretty well. I decided to use SiteSprint as motivation
+to buckle down and complete it to a point where I can invite a few organizers
+to give it a try in a "closed-beta" period. From there I'll work out any kinks
+and open it up for public use.
+
+Here are some of the things the site can do *right now*:
+
+* Users can sign up and create profiles for themselves.  "Forgot my password" and such is supported.
+* They can view (and search for) events that are happening in the future, and comment on them.
+* They can create a new event and add things to its schedule.
+* The schedule is formatted nicely.  If an event starts before 5 AM it's grouped with the previous day's events because it's probably a late night dance.
+* Venues will add links to Google Maps if the organizers put in the address.
+* Organizers can let LindyHub handle event registration for them.  They specify how they want to be paid: door, check, and/or PayPal.  If it's PayPal, LindyHub takes the email address that should receive the money and handles creating the PayPal "Buy Now" button.
+* Early registration is supported -- organizers can specify a cutoff date and the early/late prices if they like.
+* LindyHub doesn't *have* to be used for the registration.  Organizers can opt to handle registration themselves and just put the event on LindyHub to help more people find it.
+* Users can register for events quickly and easily.  LindyHub will ask them how they want to pay and tell them how to do it.
+* When they register they can allow other people to see that they're going to the event.  If they do, they'll show up in the list on the event page.
+* Organizers can see nicely formatted lists of registration/payment information and housing requests.
+
+My Goals for the Sprint (and Beyond)
+------------------------------------
+
+Some of the things I'm planning on adding to the site in during the sprint
+are:
+
+* Redesign the interface.  I'm not a designer, but I can certainly do better than the spartan design I've thrown together during development.
+* Better, Javascript-based form fields.  They'll validate the input before you even click "Submit" (so you can correct mistakes immediately) and provide nice date/time pickers for the date and time fields.  I wanted to make sure the site works 100% for people with JavaScript turned off before I started relying on it to make things pretty.
+* Mobile stylesheets for iPhone users.
+* Tagging events with tags like "lindyhop, blues, workshop, exchange, gordonwebster, etc."  This will make it easier to find events you're interested in.  This will also be easy to add.
+* "Friending" other users.  This would let you see what your friends are going to and would be awesome (for me, at least).
+* Location-based features.  LindyHub can already store your hometown and the locations of events.  It wouldn't be terribly difficult to parse this information into a latitude and longitude.  Once that's done it's simple to calculate the distance to events and say "Show me all events within 300 miles of my hometown" or "Show me everyone going to this event that lives within 30 miles of me because we might want to carpool."
+* Automatically email reminders to people a week before the event.  The emails could include links to Google Maps for the first (and other) venues to make it take only one click to print directions.  There are a lot of other things that would be nice to include too -- I've been holding off on this because it really requires the attention of a copywriter to get right.
+* Provide an easy-to-use interface for organizers to assign people that have requested housing to people that offer it.
+* Send emails to guest/host groups automatically to make sure guests have their host's contact information (and vice versa).
+* Translations into different languages.  This will be pretty simple if someone wants to volunteer to translate (I only speak English and American Sign Language myself).
+* Suggesting events a user might like.  This is something for the far future, but it would give me a chance to play around in another favorite area of mine: artificial intelligence.  I have some ideas on how to implement it but it's not critical so I'm not looking at it right now.
+
+There are a whole slew of other things I have tumbling about in my head, but
+those should be enough to give you an idea of where the site can go.
+
+**Above all, my goal is to spend as much time as it takes to create a site
+that will save organizers a few hours of their time and make it easier for
+dancers to find events they want to go to.**
+
+I *don't* want to try to create a site that will accommodate *every* event. If
+I make LindyHub flexible enough to handle Frankie 95 it will become so
+complicated that no other events will want to use it. I want it to work for
+the 85% or 90% of events that just need the most common features. Doing that
+will make it far, far easier to use, which means more people will use it.
+
+For the Nerds: What I'm Using
+-----------------------------
+
+LindyHub is built with [Django][] and [Python][].
+
+It's hosted on [WebFaction][] and uses a [PostgreSQL][] database to store its
+data.
+
+It uses [Aardvark Legs][] to keep me sane while writing the CSS, and will use
+[jQuery][] for the inline form validation.
+
+I'm happy to go further in depth if you're curious -- let me know with a
+comment.
+
+[Django]: http://www.djangoproject.com/
+[Python]: http://python.org/
+[WebFaction]: http://www.webfaction.com/?affiliate=sjl
+[PostgreSQL]: http://www.postgresql.org/
+[Aardvark Legs]: http://fecklessmind.com/2009/01/20/aardvark-css-framework/
+[jQuery]: http://jquery.com/
+
+If You're Interested, Follow My Progress!
+-----------------------------------------
+
+I'm going to be working on the site a lot over the next month. I might write
+another blog entry or two, but I'll try to post updates to
+[@lindyhub][twitter] on Twitter much more often.
+
+If there's anything specific you want to know post a comment here and I'll be
+happy to answer!
+
+[twitter]: http://twitter.com/lindyhub/
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/index.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,6 @@
+{% extends "skeleton/_listing.html" %}
+
+{% hyde
+    title: "Blog"
+    exclude: True
+%}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/feed.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,1 @@
+{% extends "skeleton/_atom.xml" %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/index.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,5 @@
+{% extends "_splash.html" %}
+
+{% hyde
+    title: ""
+%}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/projects/django-hoptoad.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,211 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "django-hoptoad"
+    snip: "Now ponies can ride the toad too."
+    created: 2009-07-25 01:16:40
+%}
+
+{% block article %}
+
+django-hoptoad is some simple Middleware for letting [Django][]-driven
+websites report their errors to [Hoptoad][]. Now [ponies][] can ride the toad
+too.
+
+You can get it from [the repository on BitBucket][repo].
+
+[Django]: http://djangoproject.com/
+[Hoptoad]: http://hoptoadapp.com/
+[ponies]: http://djangopony.com/
+[repo]: http://bitbucket.org/sjl/django-hoptoad/
+
+[TOC]
+
+Requirements
+------------
+
+django-hoptoad requires:
+
+* [Python][] 2.5+ (preferably 2.6+ as that's what I've tested it with)
+* [PyYAML][] (`pip install pyyaml` or `easy_install pyyaml`)
+* [Django][] 1.0+
+* A [Hoptoad][] account
+
+[Python]: http://python.org/
+[PyYAML]: http://pyyaml.org/
+
+Installation
+------------
+
+Grab the the django-hoptoad code by cloning the [Mercurial][] repository (or
+just [download the latest version][tip-dl] and unzip it somewhere):
+
+    hg clone http://bitbucket.org/sjl/django-hoptoad/
+
+There's a git mirror too if you *really* want it.
+
+    git clone git://github.com/sjl/django-hoptoad.git
+
+Once you download it, you can install it in the usual manner:
+
+    cd django-hoptoad
+    python setup.py install
+
+If you'd prefer to be able to update at any time by pulling down changes with
+Mercurial or git, you can symlink the module into your `site-packages`
+directory instead of using `python setup.py install`:
+
+    ln -s /full/path/to/django-hoptoad/hoptoad /full/path/to/site-packages/
+
+To make sure it works you can run:
+
+    python -c 'import hoptoad'
+
+[Mercurial]: http://mercurial.selenic.com/
+[tip-dl]: http://bitbucket.org/sjl/django-hoptoad/get/tip.zip
+
+Usage
+-----
+
+To set up a Django project to notify Hoptoad of its errors, you need to do two
+things in the `settings.py` file.
+
+First, add the `HoptoadNotifierMiddleware` as the last item in your
+`MIDDLEWARE_CLASSES` setting:
+
+    MIDDLEWARE_CLASSES = (
+        # ... other middleware classes ...
+        'hoptoad.middleware.HoptoadNotifierMiddleware',
+    )
+
+Next, you'll need to add a `HOPTOAD_API_KEY` setting. You can get the key from
+the Hoptoad project page.
+
+    HOPTOAD_API_KEY = 'Your Hoptoad API key.'
+
+Optional Settings
+-----------------
+
+There are a few extra things you can configure if you'd like to tweak the
+notification process a bit.
+
+### Notify Hoptoad While in DEBUG Mode
+
+By default the Middleware will **not** report errors to Hoptoad when your
+project is in `DEBUG` mode. The idea behind this is that if you can already
+see the error information right in the browser you probably don't need to see
+it in Hoptoad too. If you want to always notify Hoptoad of errors, even while
+in `DEBUG` mode, add the following setting:
+
+    HOPTOAD_NOTIFY_WHILE_DEBUG = True
+
+### Specify a Default Timeout
+
+The notification middleware will make sure the error notification gets to
+Hoptoad before the response gets sent back to the user. If it takes a while to
+contact Hoptoad the user will notice a delay.
+
+By default, the amount of time the notifier will wait before giving up is
+Python's "global default timeout setting". I have no idea what that is because
+the [documentation][urllib2docs] does not see fit to explain that to me.
+
+If you'd like to change that amount you can use the `HOPTOAD_TIMEOUT` setting.
+You **must** be running Python 2.6+ to use this.
+
+    HOPTOAD_TIMEOUT = 5
+
+The number is the number of seconds the notifier will wait before timing out.
+Yes, you can use a float like `0.5` to specify fractions of a second.
+
+[urllib2docs]: http://docs.python.org/library/urllib2.html
+
+### Track 404 Errors
+
+By default Hoptoad will **not** be notified of 404 (page not found) errors. If
+you'd like to change this you'll need to add the following setting:
+
+    HOPTOAD_NOTIFY_404 = True
+
+**IMPORTANT**: If you are using Django's `flatpages` app and want to track 404
+errors, you need to make sure the `FlatpageFallbackMiddleware` comes *after*
+the `HoptoadNotifierMiddleware`. If you don't do this Hoptoad will be notified
+of 404 errors even if the user actually sees a Flatpage.
+
+To track 404s while using the `flatpages` app your `MIDDLEWARE_CLASSES`
+setting should look like this:
+
+    MIDDLEWARE_CLASSES = (
+        # ... other middleware classes ...
+        'hoptoad.middleware.HoptoadNotifierMiddleware',
+        'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
+    )
+
+A couple of things to note:
+
+* If your website doesn't have a favicon specified most browsers will request it each time.  This will result in one (or possibly two, if it tries to append a slash) 404 errors for every page view.
+* At the moment all 404 errors are grouped together as "similar" errors in Hoptoad.  I am trying to figure out what causes this.
+
+### Track 403 Errors
+
+By default Hoptoad will **not** be notified of 403 (forbidden) errors. If
+you'd like to change this you'll need to add the following setting:
+
+    HOPTOAD_NOTIFY_403 = True
+
+Note:
+
+* At the moment all 403 errors are grouped together as "similar" errors in
+  Hoptoad. I am trying to figure out what causes this.
+
+### Ignore Specific User Agents
+
+If you'd like to ignore all errors from certain User Agents you can use the
+following setting:
+
+    HOPTOAD_IGNORE_AGENTS = ['MSIE 6.0', 'Trident']
+
+If any of the strings in the list appear *anywhere* in the User Agent string,
+Hoptoad will not be notified of the error.
+
+The strings are actually regular expressions, so you can be more specific if
+you like:
+
+    HOPTOAD_IGNORE_AGENTS = [r'^Mozilla.*compatible; MSIE \d+\.\d+.*$']
+
+One thing this is useful for (aside from hating on IE) is ignoring errors from
+web crawlers. Often bots will mangle URLs and if you're tracking 404 errors
+you'll see a *lot* of errors that you probably don't care about.
+
+This would probably be a good starting point for ignoring crawlers:
+
+    HOPTOAD_IGNORE_AGENTS = ['Googlebot', 'Yahoo! Slurp', 'YahooSeeker']
+
+Troubleshooting
+---------------
+
+If things don't go smoothly, the first thing to do is run the tests to see if
+they can determine what's wrong. To enable the tests you'll need to add
+django-hoptoad to your `INSTALLED_APPS` setting:
+
+    INSTALLED_APPS = (
+        # ... other apps ...
+        'hoptoad',
+        # ... other apps ...
+    )
+
+Once you've done that you can run the unit tests:
+
+    python manage.py test hoptoad
+
+**NOTE**: The unit tests are very simple at the moment. I'm working on more,
+but please feel free to submit ideas (or better yet: patches).
+
+Suggestions
+-----------
+
+This Middleware is a work in progress. If you have a suggestion or find a bug
+please [add an issue][issues] or post a comment and let me know.
+
+[issues]: http://bitbucket.org/sjl/django-hoptoad/issues/?status=new&status=open
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/projects/fuego.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,36 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Fuego"
+    snip: "Photographs of Alex. Studio."
+    created: 2009-01-19 01:25:20
+%}
+
+{% block article %}
+
+{% spaceless %}
+
+<div class="gallery">
+    <a href="/media/images/projects/{{ page.page_name }}/Fuego-4852.jpg" rel="fuego">
+        <img src="/media/images/projects/{{ page.page_name }}/Fuego-4852-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/Fuego-4887.jpg" rel="fuego">
+        <img src="/media/images/projects/{{ page.page_name }}/Fuego-4887-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/Fuego-4919.jpg" rel="fuego">
+        <img src="/media/images/projects/{{ page.page_name }}/Fuego-4919-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/Fuego-4941.jpg" rel="fuego">
+        <img src="/media/images/projects/{{ page.page_name }}/Fuego-4941-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/Fuego-4985.jpg" rel="fuego">
+        <img src="/media/images/projects/{{ page.page_name }}/Fuego-4985-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/Fuego-5133.jpg" rel="fuego">
+        <img src="/media/images/projects/{{ page.page_name }}/Fuego-5133-thumb.jpg" />
+    </a>
+</div>
+
+{% endspaceless %}
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/projects/grabtweets.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,77 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "grabtweets"
+    snip: "A simple tool for backing up your tweets."
+    created: 2009-09-12 11:02:46
+%}
+
+{% block article %}
+
+`grabtweets` is a simple tool to backup your tweets.
+
+The code is in a [Mercurial repository][repository] on [BitBucket][].
+
+[BitBucket]: http://bitbucket.org/
+
+[TOC]
+
+Installing
+----------
+
+`grabtweets` requires [Python][] 2.6 or later.
+
+To install it, you can [download][] the latest version, or clone the Mercurial
+repository:
+
+    hg clone http://bitbucket.org/sjl/grabtweets/
+
+You can put it anywhere you like.
+
+Using
+-----
+
+`grabtweets` can back up your tweets and print tweets that it has already
+archived.
+
+### Backing Up Tweets
+
+To back up your tweets, run `grabtweets` like this:
+
+    $ grabtweets.py -u USERNAME FILE
+
+`grabtweets` will pull down the 200 newest tweets from USERNAME and store them in FILE.
+
+You probably have more than 200 tweets. However, Twitter will only let you
+pull down 200 at a time and hitting the server too fast will result in Twitter
+cutting off your access for a while.
+
+To deal with this, it's best to set up `grabtweets` as a cron/launchd job that
+runs every couple of hours. Each time it runs, it will pull down the newest
+200 tweets, plus 200 older tweets if there are any available.
+
+It will take about `NUMBER_OF_TWEETS_YOU_HAVE/200` runs to finish archiving
+your tweets. Just set it up and forget about it.
+
+### Printing Backed Up Tweets
+
+To print the tweets that `grabtweets` has already backed up, run it like this:
+
+    $ grabtweets.py -p FILE
+
+[Python]: http://python.org/
+[download]: http://bitbucket.org/sjl/grabtweets/get/tip.zip
+
+Problems, Contributing, etc
+---------------------------
+
+`grabtweets` was hacked together in an hour. There are probably bugs. If you
+find any, go ahead and create an issue in the [issue tracker][].
+
+Want to fix something or add a feature? Great! Fork the [repository][] and
+send me a pull request.
+
+[issue tracker]: http://bitbucket.org/sjl/grabtweets/issues/?status=new&status=open
+[repository]: http://bitbucket.org/sjl/grabtweets/
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/projects/hg-paste.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,73 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "hg-paste"
+    snip: "Send diffs from Mercurial to various pastebin websites."
+    created: 2009-09-16 17:52:55
+%}
+
+{% block article %}
+
+hg-paste adds an `hg paste` command to Mercurial which can send diffs to
+various pastebin websites for easy sharing. You can grab the code from the
+[repository][] on BitBucket.
+
+It was inspired by [Pocoo][]'s [hgpaste][pocoopaste] extension, but is
+designed to work with public pastebin websites instead of private
+installations of [LodgeIt][].
+
+[Pocoo]: http://www.pocoo.org/
+[pocoopaste]: http://dev.pocoo.org/hg/hgpaste/
+[LodgeIt]: http://dev.pocoo.org/projects/lodgeit/
+
+[TOC]
+
+Installing
+----------
+
+Clone the repository:
+
+    hg clone http://bitbucket.org/sjl/hg-paste/
+
+Edit the `[extensions]` section in your `~/.hgrc` file:
+
+    [extensions]
+    paste = (path to)/hg-paste/paste.py
+
+Using the Command
+-----------------
+
+To paste a diff of all uncommitted changes in the working directory:
+
+    hg paste
+
+To paste the changes that revision `REV` made:
+
+    hg paste -r REV
+
+To paste the changes between revisions `REV1` and `REV2`:
+
+    hg paste -r REV1:REV2
+
+If any files are specified only those files will be included in the diffs.
+
+Several options can be used to specify more metadata about the paste:
+
+    hg paste --user Steve --title 'Progress on feature X' --keep
+
+The pastebin website to use can be specified with `--dest`. Currently only
+[dpaste.com](http://dpaste.com/) and [dpaste.org](http://dpaste.org) are
+supported.
+
+Questions, Comments, Suggestions
+--------------------------------
+
+If you find any bugs, please create an issue in the [issue tracker][issues].
+
+If you want to contribute (support for more pastebin websites would be great),
+fork the [repository][] on BitBucket and send a pull request.
+
+[issues]: http://bitbucket.org/sjl/hg-paste/issues/?status=new&status=open
+[repository]: http://bitbucket.org/sjl/hg-paste
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/projects/hg-prompt.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,167 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "hg-prompt"
+    snip: "A Mercurial extension for adding repository info to your shell prompt."
+    created: 2009-06-19 22:25:17
+%}
+
+{% block article %}
+
+hg-prompt adds an 'hg prompt' command to Mercurial for viewing repository
+information. It's designed to be used in a shell prompt. You can grab the code
+from [the repository on BitBucket](http://bitbucket.org/sjl/hg-prompt/).
+
+Here's what it looks like:
+
+![My bash prompt while using hg-prompt.](/media/images/projects/{{ page.page_name }}/prompt.png "My bash prompt while using hg-prompt.")
+
+[TOC]
+
+Requirements
+------------
+
+hg-prompt requires Python 2.5+ and (obviously) Mercurial.
+
+Installing
+----------
+
+Clone the repository:
+
+    :::text
+    $ hg clone http://bitbucket.org/sjl/hg-prompt/
+
+Edit the `[extensions]` section in your `~/.hgrc` file:
+
+    :::text
+    [extensions]
+    prompt = (path to)/hg-prompt/prompt.py
+
+Using the Command
+-----------------
+
+The `hg prompt` command takes a single string as an argument and outputs it.
+Here's a simple (and useless) example:
+
+    :::text
+    $ hg prompt "test"
+    test
+
+Keywords in curly braces can be used to output repository information:
+
+    :::text
+    $ hg prompt "currently on {branch}"
+    currently on default
+
+Keywords also have an extended form:
+
+    :::text
+    {optional text{branch}more optional text}
+
+This form will output the text and the expanded keyword **only** if the
+keyword successfully expands. This can be useful for displaying extra text
+only if it's applicable:
+
+    :::text
+    $ hg prompt "currently on {branch} and at {bookmark}"
+    currently on branch default and at 
+    
+    $ hg prompt "currently on {branch} {and at {bookmark}}"
+    currently on branch default 
+    
+    $ hg bookmark my-book
+    
+    $ hg prompt "currently on {branch} {and at {bookmark}}"
+    currently on branch default and at my-book
+
+Available Keywords
+------------------
+
+There a number of keywords available. If you have any suggestions for more
+please let me know.
+
+* **bookmark:** the current bookmark (requires the [bookmarks][] extension)
+* **branch:** the current branch
+* **node:** the (full) changeset hash of the current parent
+* **node|short:** a short form of the changeset hash of the current parent
+* **node|merge:** the (full) changeset hash of the changeset you're merging with if you're currently merging, otherwise nothing.
+* **node|merge|short:** a short form of the changeset hash of the changeset you're merging with if you're currently merging, otherwise nothing
+* **patch:** the topmost currently-applied patch (requires the mq extension)
+* **patch|count:** the number of patches in the queue
+* **patch|applied:** the number of currently applied patches
+* **patch|unapplied:** the number of unapplied patches in the queue
+* **rev:** the repository-local changeset number of the current parent
+* **rev|merge:** the repository-local changeset number of the changeset you're merging with if you're currently merging, otherwise nothing
+* **root:** the full path to the root of the current repository, without a trailing slash
+* **root|basename:** the directory name of the root of the current repository.  For example, if the repository is in `/home/u/myrepo` then this keyword would expand to `myrepo`.
+* **status:**  `!` if the repository has any changed/added/removed files, otherwise `?` if it has any untracked (but not ignored) files, otherwise nothing
+* **status|modified:** `!` if the current repository contains files that have been modified, added, removed, or deleted, otherwise nothing
+* **status|unknown:** `?` if the current repository contains untracked files, otherwise nothing
+* **status|modified|unknown:** `!` if the current repository contains files that have been modified, added, removed, or deleted, *and* `?` if it contains untracked (and not ignored) files, otherwise nothing
+* **tags:** the tags of the current parent, separated by a space
+* **tags|SEP:** the tags of the current parent, separated by `SEP`
+* **task:** the current task (requires the [tasks][] extension)
+* **tip:** the repository-local changeset number of the current tip
+* **tip|node:** the (full) changeset hash of the current tip
+* **tip|node|short:** a short form of the changeset hash of the current tip
+* **update:** `^` if the current parent is not the tip of the current branch, otherwise nothing.  In effect, this lets you see if running `hg update` would do something.
+
+[bookmarks]: http://mercurial.selenic.com/wiki/BookmarksExtension
+[tasks]: http://bitbucket.org/alu/hgtasks/wiki/Home
+
+Remote Status Keywords
+----------------------
+
+There are several keywords available to monitor the status of remote
+repositories. Because this can be an expensive operation if the remote
+repository is across a network, they cache their results in
+`.hg/prompt/cache/`. The cache is updated roughly every fifteen minutes.
+
+* **incoming:** this keyword prints nothing on its own.  If the default path contains incoming changesets the extra text will be expanded. For example: `{incoming changes{incoming}}` will expand to `incoming changes` if there are changes, or nothing otherwise.
+* **incoming|count:** the number of incoming changesets if greater than 0
+* **outgoing:** this keyword prints nothing on its own.  If the current repository contains outgoing changesets (to default) the extra text will be expanded. For example: `{outgoing changes{outgoing}}` will expand to `outgoing changes` if there are changes, or nothing otherwise.
+* **outgoing|count:** the number of outgoing changesets if greater than 0
+
+Putting it in a Bash Prompt
+---------------------------
+
+To put it in your bash prompt, edit your `~/.bashrc` file to include something
+like this:
+
+    #!bash
+    hg_ps1() {
+        hg prompt "{ on {branch}}{ at {bookmark}}{status}" 2> /dev/null
+    }
+    
+    export PS1='\u at \h in \w$(hg_ps1)\n$ '
+
+`source ~/.bashrc` after to test it out. Make sure you're in a Mercurial
+repository or you won't see anything. This little prompt will give you
+something like this:
+
+    steve at myhost in ~/src/hg-prompt on default at feature-bookmark?
+    $
+
+How about something a little more interesting?
+
+    hg_ps1() {
+        hg prompt "{[+{incoming|count}]-->}{root|basename}{/{branch}}{-->[+{outgoing|count}]}{ at {bookmark}}{status}" 2> /dev/null
+    }
+    
+    export PS1='$(hg_ps1)\n\u at \h in \w\n$ '
+
+And the result (this example assumes one incoming changeset and two outgoing):
+
+    [+1]-->hg-prompt/default-->[+2] at feature-bookmark
+    steve at myhost in ~/src/hg-prompt
+    $
+
+Questions, Comments, Suggestions
+--------------------------------
+
+The code was kind of thrown together in one night after I got tired of
+chaining three or four hg runs together to get what I wanted. I'm sure it's
+not perfect, so if you've got a way to improve it please [add an
+issue](http://bitbucket.org/sjl/hg-prompt/issues/) and let me know.
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/projects/hgtab.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,114 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "hgtab"
+    snip: "Smarter tab completion for Mercurial in bash."
+    created: 2009-03-10 20:22:44
+%}
+
+{% block article %}
+
+hgtab was created to provide smarter tab completion for Mercurial in bash.
+
+**UPDATE**: Apparently there's already [tab completion in
+Mercurial](http://www.selenic.com/hg/file/11efa41037e2/contrib/bash_completion)!
+It's way better than this, *use that*! It should probably be better documented
+though &ndash; I posted this yesterday and it's already the top four results
+for "mercurial tab completion" on Google...
+
+If I've missed something you'd really like tab completed, post an issue on the
+issue tracker and I'll do my best to implement it. My bash scripting skills
+are almost non-existent, so if you improve this (or port it to another shell)
+feel free to send a pull request!
+
+You can download hgtab from its [BitBucket
+repository](http://source.stevelosh.com/hgtab/).
+
+## Installing
+
+All you need to do to use hgtab is source it. There are three ways to do this,
+ranging from easy and ugly to slightly less easy and more elegant.
+
+### OPTION 1: Easy, Ugly
+
+Copy the contents of hgtab-bash.sh into your ~/.bashrc file.
+
+### OPTION 2: Harder, Less Ugly
+
+Download hgtab-bash.sh and place the following line somewhere in your
+~/.bashrc file:
+
+    source ~/path/to/hgtab/hgtab-bash.sh
+
+### OPTION 3: Hardest, Elegant
+
+Clone this repository somewhere with this command:
+
+    hg clone http://bitbucket.org/sjl/hgtab/
+
+Add the following line to your ~/.bashrc file:
+
+    source ~/path/to/hgtab/hgtab-bash.sh
+
+If you use this method you can update the file by pulling down the changes
+from this repository:
+
+    cd ~/path/to/hgtab
+    hg pull
+
+## Using
+
+Once hgtab is sourced it'll add some nifty tab completion features in your
+shell. For example, you can tab complete Mercurial commands:
+
+    #!console
+    sjl at grendel in test $  hg re<tab(s)>
+    recover  remove   rename   resolve  revert
+    sjl at grendel in test $  hg re
+
+When you're using a command that wants a revision as a parameter, hitting tab
+will complete on tags (and bookmarks) and branches.
+
+    #!console
+    sjl at grendel in test $  hg branches
+    blue                          20:f05ca6eb51a1
+    red                           16:8262f0345f41 (inactive)
+    default                       15:67f959b8deb8 (inactive)
+    sjl at grendel in test $  hg book
+     * dev-1.0                   20:f05ca6eb51a1
+    sjl at grendel in test $  hg tags
+    tip                               20:f05ca6eb51a1
+    dev-1.0                           20:f05ca6eb51a1
+    beta                              18:f3ab9bf730f7
+    alpha                             17:ca802019f04f
+    
+    sjl at grendel in test $  hg update <tab(s)>
+    alpha    beta     blue     default  dev-1.0  red      tip
+    sjl at grendel in test $  hg update b<tab(s)>
+    beta  blue  
+    sjl at grendel in test $  hg update b
+    
+    sjl at grendel in test $  hg diff -r b<tab(s)>
+    beta  blue  
+    sjl at grendel in test $  hg diff -r b
+
+It will also complete remote paths when you're pushing or pulling.
+
+    #!console
+    sjl at grendel in test $  hg paths
+    alice-dev = http://alice-dev
+    alice-stable = http://alice-stable
+    bob = http://bob
+    default = ssh://hg@bitbucket.org/sjl/hgtag/
+    
+    sjl at grendel in test $  hg push <tab(s)>
+    alice-dev     alice-stable  bob           default
+    sjl at grendel in test $  hg push
+    
+    sjl at grendel in test $  hg pull alice-<tab(s)>
+    alice-dev     alice-stable  
+    sjl at grendel in test $  hg pull alice-
+
+Enjoy!
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/projects/index.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,6 @@
+{% extends "skeleton/_listing.html" %}
+
+{% hyde
+    title: "Projects"
+    exclude: True
+%}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/projects/lindyjam-com.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,152 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "lindyjam.com"
+    snip: "A page for a local weekly swing dance event (and more)."
+    created: 2009-01-21 18:28:35
+%}
+
+{% block article %}
+
+A few days ago I released the new [Lindy Jam][] website. Lindy Jam is a weekly
+swing dance in Rochester, NY. I wanted to create a site that was useful for
+those that attend the event but also more than just a "here's when it is and
+how to get there" page.
+
+[Lindy Jam]: http://lindyjam.com/
+
+![lindyjam.com screenshot](/media/images/projects/{{ page.page_name }}/lindyjamcom-splash.png "Screenshot of the Lindy Jam site.")
+
+Design
+------
+
+Let me preface this section by saying: "I'm not a graphic designer." Yes, I
+appreciate good design and typography, but I simply haven't studied it as much
+as I'd like. That might change in the future, but for now I'll make due with
+the knowledge I have.
+
+There are very few images used on the site; the background stripes and the
+splash page photo(s) comprise all of them. I did this for a few reasons:
+
+* It saved me time.
+* The site loads faster.
+* The site scales to larger or smaller sizes very gracefully.
+
+I tried to keep things as clean as possible while still being useful. Comments
+and error messages are displayed immediately, without reloading the page. This
+makes it easier to see what you've done (or what went wrong) right off the
+bat.
+
+I'm not 100% pleased with how it came out, but it will do until I learn more
+about design. If you have advice or suggestions about the design, please
+[email me][]!
+
+[email me]: mailto:steve@stevelosh.com
+
+Pages
+-----
+
+### About
+
+The most important part of the site is probably the [About][] page, because it
+tells people when and where the event happens. It's as simple and to the point
+as I could make it so people can get the information they're looking for right
+away. It's linked right from the splash page so it's easier to find.
+
+[About]: http://lindyjam.com/about/
+
+### DJ Schedule
+
+Another important piece of the site is the [DJ Schedule][] page. Every week
+someone can sign up to DJ the event. They get in for free, and we get to hear
+a wider variety of music. The schedule page makes it easy to sign up for a
+week in the near future.
+
+When you sign up to DJ you can also enter your email address or cell phone
+number (or both) if you'd like to be reminded. I know that sometimes I've
+almost forgotten to bring my laptop (and arrive right on time), so I hope that
+this feature will be useful to other DJs too.
+
+[DJ Schedule]: http://lindyjam.com/schedule/
+
+### Blog
+
+One thing I believe our Lindy Hop scene lacks is a place for people to write
+thoughtful, well-crafted articles about the scene. I hope the Lindy Jam
+[Blog][] can become such a place.
+
+It's a fairly simple blog; entries and comments are written in [Markdown][] so
+authors don't need to know HTML to make their articles look nice. Anyone can
+comment without signing up for anything, so I hope people will take advantage
+of that and discuss the articles.
+
+[Blog]: http://lindyjam.com/blog/
+[Markdown]: http://daringfireball.net/projects/markdown/
+
+### Links
+
+Most sites like this have a list of links to other sites that their viewers
+might be interested in, and this site is no different. The [Links][] page is a
+simple, clean list of links that anyone can contribute to. If someone knows of
+a great page we haven't listed, they can submit it and it will appear on the
+page as soon as it's been approved.
+
+[Links]: http://lindyjam.com/links/
+
+### Quotes
+
+Along the top of every page is a random quote. Right now there aren't very
+many, but I hope that people will submit some more by going to the [Quotes][]
+page or by text messaging them to <quotes@lindyjam.com>.
+
+I think the quotes add a more personal touch and allowing anyone to add one
+can really make it a "community" site.
+
+[Quotes]: http://lindyjam.com/quotes/
+
+### RSS
+
+We nerds love our [RSS][] feeds, so I've implemented a couple of different
+feeds that people can use to stay up to date.
+
+[RSS]: http://lindyjam.com/rss/
+
+Implementation
+--------------
+
+The site was built with [Django][] because it makes it very, very easy to get
+a dynamic site like this up and running quickly. I use [Fabric][] to deploy it
+(check out [this
+entry](http://stevelosh.com/blog/entry/2009/1/15/deploying-site-fabric-and-mercurial/)
+on my personal blog for more information about that). All of the fancy effects
+use [jQuery][] so I can avoid programming them from scratch in javascript (and
+tearing my hair out).
+
+One thing I would do differently if I were to design the site all over again
+is use a CSS framework like [Blueprint][]. I used Blueprint for my personal
+site and it made things far, far easier than writing the layout in CSS from
+scratch. I definitely recommend it if you want to keep your sanity.
+
+The site itself is hosted on [WebFaction][]. I use them to host my own site
+too and they're fantastic. Setting up a Django or Rails (or any other type) of
+site is quick and easy, and they're very cheap. If you're looking for a web
+host you should check them out.
+
+The site is open source if you'd like to take a look at what makes it tick.
+You can browse or download the code from the [Mercurial repository][] on
+BitBucket.
+
+[Django]: http://djangoproject.com/
+[Fabric]: http://www.nongnu.org/fab/
+[jQuery]: http://jquery.com/
+[Blueprint]: http://www.blueprintcss.org/
+[WebFaction]: http://www.webfaction.com/signup?affiliate=sjl
+[Mercurial repository]: http://bitbucket.org/sjl/lindyjam/
+
+Feedback
+--------
+
+If you have any comments or questions about the site please let me know! You
+can post them here or [email me][].
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/projects/stevelosh-com.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,101 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "stevelosh.com"
+    snip: "This website."
+    created: 2009-01-11 15:40:26
+%}
+
+{% block article %}
+
+For a long time I used [Squarespace][] to create and host my personal website.
+It's a great service, and I highly recommend it to anyone that needs a simple,
+easy, beautiful site.
+
+Recently, however, I've started learning more and more about web design and I
+decided to completely revamp my website and build it myself from the ground
+up. This is the result.
+
+Design
+------
+
+I like simplicity. In all areas of my life (music, dancing, photography,
+programming, design, etc) I'm striving to make everything I do as simple,
+clean, and elegant as possible. That's why I went with such a minimal design
+for the site.
+
+I haven't used any graphics in the layout for a few reasons. First, I'm not
+very good at making them. Second, I want the site to load quickly, even on
+phones, and scale gracefully for accessibility. Third, I wanted the interface
+to be as uncluttered as possible so the content of the site would be front and
+center.
+
+I also stuck to a minimum of color. The only items that have any color on the
+site are any photographs that I post and the links. I did this because I'm not
+a graphic designer and so I haven't studied color enough to know how to use it
+well.
+
+One last thing I tried to keep in mind was sticking to a baseline rhythm for
+some elements of the site. The home page, blog entry list, and project list
+all line up with the links in the right sidebar. I think it gives the layout a
+more stable feel.
+
+Implementation
+------------
+
+This website was written in [Python][] using the [Django][] framework. Django
+makes it really easy to write useful web apps quickly and cleanly. I love it.
+
+[Blueprint][] kept me sane while writing the CSS. Grid layouts are no longer a
+nightmare!
+
+I rely pretty heavily on [Markdown][] throughout the site. The blog entries
+and static pages are all written in Markdown and parsed to XHTML later. This
+might not be the fastest way to do things but processor time is cheap and my
+time isn't.
+
+The Markdown-based editor and preview for commenting is the wonderful [WMD][].
+It's clean, simple, and does exactly what I want it to do. Most of the other
+Javascript magic comes from [jQuery][]. I use the [jQuery form validation
+plugin][form validation] in a couple of places to make checking input easier.
+
+For site statistics I'm relying on the fantastic [Mint][]. It's got a gorgeous
+interface and is absurdly simple to install. Plus it's hosted on my own host
+so I have control. It's also just a one time fee, unlike some other site stat
+packages that charge monthly.
+
+My development process is pretty simple. I use [TextMate][] to edit the code
+and a [Mercurial][] repository to store it and protect against accidents. To
+deploy, I push my local changes to a private repository on [Bitbucket.org][],
+and then use [Fabric][] to pull those changes down to the server and restart
+if necessary.
+
+The site is hosted by [WebFaction][]. If you're looking for a web host for
+Django or Rails sites (or any other kind, really) you should definitely
+consider them. Not only do they make installing Django or Rails very easy,
+they're absurdly cheap: 10gb disk space and 600gb/month bandwidth is less than
+$10 a month. I'd recommend them to anyone.
+
+It's Open Source, Too!
+----------------------
+
+Want to see what makes this site tick? Want to make it tick more smoothly?
+Feel free to head over to <http://bitbucket.org/sjl/stevelosh> and take a look
+at the code.
+
+[Squarespace]: http://www.squarespace.com/
+[Python]: http://python.org
+[Django]: http://djangoproject.com
+[Blueprint]: http://www.blueprintcss.org/
+[Markdown]: http://daringfireball.net/projects/markdown/
+[WMD]: http://wmd-editor.com/
+[jQuery]: http://jquery.com
+[form validation]: http://bassistance.de/jquery-plugins/jquery-plugin-validation/
+[TextMate]: http://macromates.com/
+[Mercurial]: http://www.selenic.com/mercurial/wiki/
+[Bitbucket.org]: http://www.bitbucket.org/
+[Fabric]: http://www.nongnu.org/fab/
+[Mint]: http://haveamint.com/
+[WebFaction]: http://www.webfaction.com/signup?affiliate=sjl
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/projects/t.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,233 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "t"
+    snip: "A command-line todo list manager for people that want to <em>finish</em> tasks, not organize them."
+    created: 2009-09-11 19:03:29
+%}
+
+{% block article %}
+
+`t` is a command-line todo list manager for people that want to *finish*
+tasks, not organize them.
+
+The code is in a [Mercurial repository][] on [BitBucket][].
+
+[BitBucket]: http://bitbucket.org/
+
+[TOC]
+
+Why t?
+------
+
+Yeah, I know, *another* command-line todo list manager. Several others already
+exist ([todo.txt][] and [TaskWarrior][] come to mind), so why make another
+one?
+
+[todo.txt]: http://ginatrapani.github.com/todo.txt-cli/
+[TaskWarrior]: http://taskwarrior.org/projects/show/taskwarrior/
+
+### It Does the Simplest Thing That Could Possibly Work
+
+Todo.txt and TaskWarrior are feature-packed. They let you tag tasks, split
+them into projects, set priorities, order them, color-code them, and much
+more.
+
+**That's the problem.**
+
+It's easy to say "I'll just organize my todo list a bit" and spend 15 minutes
+tagging your tasks. In those 15 minutes you probably could have *finished* a
+couple of them.
+
+`t` was inspired by [j][]. It's simple, messy, has almost no features, and is
+extremely effective at the one thing it does. With `t` the only way to make
+your todo list prettier is to **finish some damn tasks**.
+
+[j]: http://github.com/rupa/j2/
+
+### It's Flexible
+
+`t`'s simplicity makes it extremely flexible.
+
+Want to edit a bunch of tasks at once? Open the list in a text editor.
+
+Want to view the lists on a computer that doesn't have `t` installed? Open the
+list in a text editor.
+
+Want to synchronize the list across a couple of computers? Keep your task
+lists in a [Dropbox][] folder.
+
+Want to use it as a distributed bug tracking system like [BugsEverywhere][]?
+Make the task list a `bugs` file in the project repository.
+
+[Dropbox]: https://www.getdropbox.com/
+[BugsEverywhere]: http://bugseverywhere.org/
+
+### It Plays Nice with Version Control
+
+Other systems keep your tasks in a plain text file. This is a good thing, and
+`t` follows their lead.
+
+However, some of them append new tasks to the end of the file when you create
+them. This is not good if you're using a version control system to let more
+than one person edit a todo list. If two people add a task and then try to
+merge, they'll get a conflict and have to resolve it manually.
+
+`t` uses random IDs (actually SHA1 hashes) to order the todo list files. Once
+the list has a couple of tasks in it, adding more is far less likely to cause
+a merge conflict because the list is sorted.
+
+Installing t
+------------
+
+`t` requires [Python][] 2.5 or newer, and some form of UNIX-like shell (bash
+works well). It works on Linux, OS X, and Windows (with [Cygwin][]).
+
+[Python]: http://python.org/
+[Cygwin]: http://www.cygwin.com/
+
+Installing and setting up `t` will take about one minute.
+
+First, [download][] the newest version or clone the Mercurial repository ( `hg
+clone http://bitbucket.org/sjl/t/` ). Put it anywhere you like.
+
+[download]: http://bitbucket.org/sjl/t/get/tip.zip
+
+Next, decide where you want to keep your todo lists. I put mine in `~/tasks`.
+Create that directory:
+
+    mkdir ~/tasks
+
+Finally, set up an alias to run `t`. Put something like this in your
+`~/.bashrc` file:
+
+    alias t='python ~/path/to/t.py --task-dir ~/tasks --list tasks'
+
+Make sure you run `source ~/.bashrc` or restart your terminal window to make
+the alias take effect.
+
+Using t
+-------
+
+`t` is quick and easy to use.
+
+### Add a Task
+
+To add a task, use `t [task description]`:
+
+    $ t Clean the apartment.
+    $ t Write chapter 10 of the novel.
+    $ t Buy more beer.
+    $
+
+### List Your Tasks
+
+Listing your tasks is even easier -- just use `t`:
+
+    $ t
+    9  - Buy more beer.
+    30 - Clean the apartment.
+    31 - Write chapter 10 of the novel.
+    $
+
+`t` will list all of your unfinished tasks and their IDs.
+
+### Finish a Task
+
+After you're done with something, use `t -f ID` to finish it:
+
+    $ t -f 31
+    $ t
+    9  - Buy more beer.
+    30 - Clean the apartment.
+    $
+
+### Edit a Task
+
+Sometimes you might want to change the wording of a task. You can use `t -e ID
+[new description]` to do that:
+
+    $ t -e 30 Clean the entire apartment.
+    $ t
+    9  - Buy more beer.
+    30 - Clean the entire apartment.
+    $
+
+Yes, nerds, you can use sed-style substitution strings:
+
+    $ t -e 9 /more/a lot more/
+    $ t
+    9  - Buy a lot more beer.
+    30 - Clean the entire apartment.
+    $
+
+Tips and Tricks
+---------------
+
+`t` might be simple, but it can do a lot of interesting things.
+
+### Count Your Tasks
+
+Counting your tasks is simple using the `wc` program:
+
+    $ t | wc -l
+          2
+    $
+
+### Put Your Task Count in Your Bash Prompt
+
+Want a count of your tasks right in your prompt?  Edit your `~/.bashrc` file:
+
+    export PS1="[$(t | wc -l | sed -e's/ *//')] $PS1"
+
+Now you've got a prompt that looks something like this:
+
+    [2] $ t -f 30
+    [1] $ t Feed the cat.
+    [2] $
+
+### Multiple Lists
+
+`t` is for people that want to *do* tasks, not organize them. With that said,
+sometimes it's useful to be able to have at least *one* level of organization.
+To split up your tasks into different lists you can add a few more aliases:
+
+    alias g='python ~/path/to/t.py --task-dir ~/tasks --list groceries'
+    alias m='python ~/path/to/t.py --task-dir ~/tasks --list music-to-buy'
+    alias w='python ~/path/to/t.py --task-dir ~/tasks --list wines-to-try'
+
+### Distributed Bugtracking
+
+Like the idea of distributed bug trackers like [BugsEverywhere][], but don't
+want to use such a heavyweight system? You can use `t` instead.
+
+Add another alias to your `~/.bashrc` file:
+
+    alias b='python ~/path/to/t.py --task-dir . --list bugs'
+
+Now when you're in your project directory you can use `b` to manage the list
+of bugs/tasks for that project. Add the `bugs` file to version control and
+you're all set.
+
+Even people without `t` installed can view the bug list, because it's plain
+text.
+
+Problems, Contributions, Etc
+----------------------------
+
+`t` was hacked together in a couple of nights to fit my needs. If you use it
+and find a bug, please let me know.
+
+If you want to request a feature feel free, but remember that `t` is meant to
+be simple. If you need anything beyond the basics you might want to look at
+[todo.txt][] or [TaskWarrior][] instead. They're great tools with lots of
+bells and whistles.
+
+If you want to contribute code to `t`, that's great! Fork the [Mercurial
+repository][] on BitBucket or the [git mirror][] on GitHub and send me a pull
+request.
+
+[Mercurial repository]: http://bitbucket.org/sjl/t/
+[git mirror]: http://github.com/sjl/t/
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/projects/women-in-water.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,46 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Women in Water"
+    snip: "Photographs of women in Lake Ontario."
+    created: 2009-08-04 18:57:36
+%}
+
+{% block article %}
+
+<div class="gallery">
+    <a href="/media/images/projects/{{ page.page_name }}/erin-tele.jpg" rel="wiw">
+        <img src="/media/images/projects/{{ page.page_name }}/erin-tele-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/alex-tele.jpg" rel="wiw">
+        <img src="/media/images/projects/{{ page.page_name }}/alex-tele-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/lizza-tele.jpg" rel="wiw">
+        <img src="/media/images/projects/{{ page.page_name }}/lizza-tele-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/leah-tele.jpg" rel="wiw">
+        <img src="/media/images/projects/{{ page.page_name }}/leah-tele-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/anna-tele.jpg" rel="wiw">
+        <img src="/media/images/projects/{{ page.page_name }}/anna-tele-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/erin-wide.jpg" rel="wiw">
+        <img src="/media/images/projects/{{ page.page_name }}/erin-wide-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/alex-wide.jpg" rel="wiw">
+        <img src="/media/images/projects/{{ page.page_name }}/alex-wide-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/lizza-wide.jpg" rel="wiw">
+        <img src="/media/images/projects/{{ page.page_name }}/lizza-wide-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/leah-wide.jpg" rel="wiw">
+        <img src="/media/images/projects/{{ page.page_name }}/leah-wide-thumb.jpg" />
+    </a>
+    <a href="/media/images/projects/{{ page.page_name }}/anna-wide.jpg" rel="wiw">
+        <img src="/media/images/projects/{{ page.page_name }}/anna-wide-thumb.jpg" />
+    </a>
+</div>
+
+This is still a work in progress.
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/resume/resume.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,176 @@
+{% extends "_flatpage.html" %}
+
+{% hyde
+    title: "Résumé"
+    exclude: True
+%}
+
+{% block article %}
+
+I'm Steve.  I'm a programmer from Rochester, NY.  I graduated from [Rochester Institute of Technology][] in 2008 with a Bachelor's degree in [Computer Science][].
+
+I'm currently most interested in rapid web development, version control, and artificial intelligence.  I'm open to both freelance and full-time work.
+
+If you'd *really* like to get to know me you should look at the [projects][] and [blog posts][] I've written, or cut to the chase and look at my [code][].
+
+[Rochester Institute of Technology]: http://rit.edu/
+[Computer Science]: http://www.cs.rit.edu/
+[projects]: /projects/
+[blog posts]: /blog/
+[code]: http://bitbucket.org/sjl/
+
+## Skills & Interests
+
+I'm passionate about programming.  It may sound odd, but there are aspects of programming that I find beautiful (in every sense of the word).
+
+### Languages
+
+My favorite programming language at the moment is [Python][].  It's elegant, readable, powerful, and makes it easy to *get things done*.
+
+I've also had experience with [Java][], [C][], [C++][], [Lisp][], [SQL][] and [PL/SQL][], [JavaScript][], [Groovy][], and [bash scripting][].  I'm familiar with a number of markup and templating languages, including [XHTML][], [XML][], [CSS][], [JSON][], [Markdown][], [Django][]'s template system, and [Jinja2][].
+
+In my free time I'm working on learning [R][].
+
+[Python]: http://www.python.org/
+[Java]: http://java.sun.com/
+[C]: http://en.wikipedia.org/wiki/C_(programming_language)
+[C++]: http://en.wikipedia.org/wiki/C%2B%2B
+[Lisp]: http://en.wikipedia.org/wiki/Lisp_(programming_language)
+[SQL]: http://en.wikipedia.org/wiki/SQL
+[PL/SQL]: http://en.wikipedia.org/wiki/PL/SQL
+[JavaScript]: http://en.wikipedia.org/wiki/JavaScript
+[Groovy]: http://groovy.codehaus.org/
+[bash scripting]: http://www.gnu.org/software/bash/
+[XHTML]: http://www.w3.org/TR/xhtml1/
+[XML]: http://www.w3.org/XML/
+[CSS]: http://www.w3.org/TR/CSS/
+[JSON]: http://www.json.org/
+[Markdown]: http://daringfireball.net/projects/markdown/
+[Jinja2]: http://jinja.pocoo.org/2/
+[R]: http://www.r-project.org/
+
+### Web Development
+
+For web development I gravitate toward the [Django][] framework.  Django bills itself as "The Web framework for professionals with deadlines" and this strikes a chord with me.
+
+I've used the [CherryPy][] framework for smaller (but still dynamic) projects that don't need the additional functionality of Django.
+
+I hate writing repetitive, difficult-to-maintain code.  Even when writing completely static websites I prefer to take advantage of templating languages.  To do that I use [Hyde][] and [Blatter][], both of which generate static HTML from templates.
+
+I've used several CSS frameworks including [Blueprint][], [Tripoli][] and [aardvark legs][].  Of these I now prefer aardvark legs because it makes setting up a beautiful vertical rhythm simple and doesn't impose itself on the horizontal layout.
+
+When writing [JavaScript][] I use [jQuery][] to eliminate a lot of the tediousness and create elegant code.
+
+[Django]: http://www.djangoproject.com/
+[CherryPy]: http://www.cherrypy.org/
+[Blueprint]: http://www.blueprintcss.org/
+[Tripoli]: http://devkick.com/lab/tripoli/
+[aardvark legs]: http://fecklessmind.com/2009/01/20/aardvark-css-framework/
+[Hyde]: http://github.com/lakshmivyas/hyde
+[Blatter]: http://bitbucket.org/jek/blatter/
+[jQuery]: http://jquery.com/
+
+### Version Control
+
+I believe version control is essential for a project of almost any size, and lately the concepts behind it have captured my interest.
+
+In my personal work I use [Mercurial][] (usually with [BitBucket][]).  I've [contributed][] several minor patches to the Mercurial core and written two extensions: [hg-prompt][] and [hg-paste][].
+
+I know my way around [Subversion][], [CVS][], and [git][] as well.
+
+[Mercurial]: http://www.selenic.com/mercurial/
+[BitBucket]: http://bitbucket.org/
+[Subversion]: http://subversion.tigris.org/
+[CVS]: http://www.nongnu.org/cvs/
+[git]: http://git-scm.com/
+[contributed]: http://selenic.com/repo/hg/log?rev=Steve+Losh
+[hg-prompt]: /projects/hg-prompt/
+[hg-paste]: /projects/hg-paste/
+
+### How I Work
+
+For my personal work I use [Mac OS X][].  I'm comfortable in [Linux][] and can deal with [Windows][] (though I don't enjoy it).
+
+I use [TextMate][] and [vim][] for coding, [CSSEdit][] when designing, [Mercurial][] for version control, [t][] to manage my personal tasks, and deploy through [SSH][] with [fabric][].
+
+[Mac OS X]: http://www.apple.com/macosx/
+[TextMate]: http://macromates.com/
+[SSH]: http://en.wikipedia.org/wiki/Secure_Shell
+[fabric]: http://www.nongnu.org/fab/
+[Linux]: http://www.linux.org/
+[Windows]: http://www.microsoft.com/WINDOWS/
+[vim]: http://www.vim.org/
+[CSSEdit]: http://macrabbit.com/cssedit/
+[t]: /projects/t/
+
+## Personal Projects
+
+You can find some of my pet projects on the [projects][] page.
+
+Lately I've been working on a few new things that aren't quite ready for general use, but are getting close:
+
+* [hg-review][]: a code-review extension for Mercurial.
+* [LindyHub][]: a site like BitBucket or GitHub for dancers.
+* [hg-letterpress][]: a new theme for [Mercurial][]'s hgweb system.
+* [tinpan][]: a language-agnostic, vcs-agnostic continuous integration system.
+
+[hg-review]: http://bitbucket.org/sjl/hg-review/
+[LindyHub]: http://test.lindyhub.com/
+[hg-letterpress]: http://hg.stevelosh.com/hg-letterpress/
+[tinpan]: http://bitbucket.org/sjl/tinpan/
+
+## Full-Time Work Experience
+
+I completed two six-month [co-ops][] while at [RIT][].  Since I graduated I've worked full time for about a year.
+
+[co-ops]: https://www.rit.edu/about/coop_careers.html
+[RIT]: http://rit.edu/
+
+### Software Engineer at [PAETEC][]
+
+*Fairport, NY from June 2008 to the present.*
+
+At [PAETEC][] I contribute to a number of projects.  I maintain and implement new features for web applications in [Java][] using the [Oracle E-Business Suite][] and work on underlying [SQL][] and [PL/SQL][] code for our databases.
+
+[PAETEC]: http://paetec.com/
+[Oracle E-Business Suite]: http://www.oracle.com/applications/e-business-suite.html
+
+### Data Architecture Co-op at [Excellus BlueCross BlueShield][]
+
+*Rochester, NY from June 2007 to November 2007.*
+
+At [Excellus][] I developed software in [Java][] to interact with and manage databases of customer and provider information stored on a mainframe.  I also created and updated [JUnit][] and [Jemmy][] tests for this software.
+
+[Excellus BlueCross BlueShield]: https://www.excellusbcbs.com/
+[Excellus]: https://www.excellusbcbs.com/
+[JUnit]: http://www.junit.org/
+[Jemmy]: http://jemmy.dev.java.net/
+
+### Managed Services Programmer at [RightNow Technologies][]
+
+*Pittsford, NY from June 2006 to November 2006.*
+
+During my co-op at [RightNow][] I developed a set of tools to test the effectiveness of voice-automated telephone systems.  These tools were written in a combination of [bash scripting][] and [Python][].  I assisted in generating statistics about the effectiveness of these systems for customers.
+
+[RightNow Technologies]: http://www.rightnow.com/
+[RightNow]: http://www.rightnow.com/
+
+## Contact Me
+
+If you'd like to get in touch with me, you can use any method you like.
+
+My **email address** is: <steve@stevelosh.com>  
+My **phone number** is: (570) 417-1392  
+My **skype username** is: steve.losh  
+My **mailing address** is: 150 Park Avenue, Apartment 7, Rochester, NY 14607
+
+You can also find me on [Twitter][], [Flickr][], [BitBucket][], [GitHub][], [BrightKite][], or [DjangoPeople][].
+
+[Twitter]: http://twitter.com/stevelosh/
+[Flickr]: http://www.flickr.com/photos/sjl7678/
+[BitBucket]: http://bitbucket.org/sjl/
+[GitHub]: http://github.com/sjl/
+[BrightKite]: http://brightkite.com/people/stevelosh/
+[DjangoPeople]: http://djangopeople.net/stevelosh/
+
+{% endblock %}
\ No newline at end of file
--- a/convert-comments.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-
-from django.core.management import setup_environ
-import settings
-setup_environ(settings)
-
-from markdown import Markdown
-from django.contrib.comments.models import Comment
-from django.contrib.sites.models import Site
-from stevelosh.blog.models import Comment as BlogComment
-from stevelosh.projects.models import Comment as ProjectComment
-
-
-mdown = Markdown()
-
-site = Site.objects.all()[0]
-blog_comments = BlogComment.objects.filter(spam=False)
-project_comments = ProjectComment.objects.filter(spam=False)
-
-for bc in blog_comments:
-    c = Comment()
-    c.content_object = bc.entry
-    c.user_name = bc.name
-    c.comment = mdown.convert(bc.body)
-    c.submit_date = bc.submitted
-    c.site = site
-    c.is_public = True
-    c.is_removed = False
-    c.save()
-    # print 'http://%s%s' % (site.domain, c.content_object.get_absolute_url())
-
-for pc in project_comments:
-    c = Comment()
-    c.content_object = pc.project
-    c.user_name = pc.name
-    c.comment = mdown.convert(pc.body)
-    c.submit_date = pc.submitted
-    c.site = site
-    c.is_public = True
-    c.is_removed = False
-    c.save()
-    # print 'http://%s%s' % (site.domain, c.content_object.get_absolute_url())
--- a/deploy-template.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-# Rename this to deploy.py when you've filled in everything.
-
-DATABASE_ENGINE = ''
-DATABASE_NAME = ''
-DATABASE_USER = ''
-DATABASE_PASSWORD = ''
-DATABASE_HOST = ''
-DATABASE_PORT = ''
-
-DEBUG = False
-
-# The longer the better.  Django automatically generates one for you when you 
-# start a new project.
-SECRET_KEY = ''
-
-AKISMET_API_KEY = ''
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fabfile.py	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,34 @@
+from fabric.api import *
+import os
+import fabric.contrib.project as project
+
+PROD = 'sjl.webfactional.com'
+DEST_PATH = '/home/sjl/webapps/slc/'
+ROOT_PATH = os.path.abspath(os.path.dirname(__file__))
+DEPLOY_PATH = os.path.join(ROOT_PATH, 'deploy')
+
+def clean():
+    local('rm -rf ./deploy')
+
+def regen():
+    clean()
+    local('hyde -g -s .')
+
+def serve():
+    local('hyde -w -s .')
+
+def reserve():
+    regen()
+    serve()
+
+def smush():
+    local('smusher ./media/images')
+
+@hosts(PROD)
+def publish():
+    regen()
+    project.rsync_project(
+        remote_dir=DEST_PATH,
+        local_dir=DEPLOY_PATH.rstrip('/') + '/',
+        delete=True
+    )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/layout/_flatpage.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,13 @@
+{% extends "skeleton/_base.html" %}
+
+{% block content %}
+    <div id="leaf-title"><h1>{{ page.title|safe|typogrify }}</h1></div>
+    
+    <div id="leaf-content">
+        {% filter typogrify %}
+            {% markdown toc def_list %}
+                {% block article %}{% endblock %}
+            {% endmarkdown %}
+        {% endfilter %}
+    </div>
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/layout/_post.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,33 @@
+{% extends "skeleton/_base.html" %}
+
+{% block content %}
+    <div id="leaf-title">
+        <h1><a href="{{ page.url }}">{{ page.title|safe|typogrify }}</a></h1>
+    </div>
+    
+    <div id="leaf-stats"><p>Posted on {{ page.created|date:"l, F j, Y" }} ({{ page.created|timesince }} ago).</p></div>
+    
+    <div id="leaf-content">
+        {% filter typogrify %}
+            {% article %}
+                {% filter typogrify %}
+                    {% markdown toc def_list %}
+                        {% block article %}{% endblock %}
+                    {% endmarkdown %}
+                {% endfilter %}
+            {% endarticle %}
+        {% endfilter %}
+    </div>
+    
+    <h1 id="comment-header">Comments</h1>
+    
+    <div id="disqus_thread"></div>
+    <script type="text/javascript" src="http://disqus.com/forums/stevelosh/embed.js"></script>
+    <noscript>
+        <a href="http://disqus.com/forums/stevelosh/?url=ref">View the discussion thread.</a>
+    </noscript>
+    <a href="http://disqus.com" class="dsq-brlink">
+        comments powered by
+        <span class="logo-disqus">Disqus</span>
+    </a>
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/layout/_splash.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,15 @@
+{% extends "skeleton/_base.html" %}
+
+{% block content %}
+    {% filter typogrify %}
+        <div id="splash-info">
+            <ul>
+                <li>I like writing. &raquo;</li>
+                <li>What makes me tick. &raquo;</li>
+                <li>Some things I’ve made. &raquo;</li>
+                <li>More about me. &raquo;</li>
+                <li>Atom feed. &raquo;</li>
+            </ul>
+        </div>
+    {% endfilter %}
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/layout/skeleton/_atom.xml	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+{% spaceless %}
+
+<feed xmlns="http://www.w3.org/2005/Atom">
+    <title>{% block title %}{{ site.name }}{% endblock %}</title>
+    
+    {% block self_url %}
+        <link href="{{ page.node.full_url }}/feed/" rel="self" />
+    {% endblock %}
+    
+    {% block site_url %}
+        <link href="{{ site.full_url }}"/>
+    {% endblock %}
+    
+    {% block feed_extra %}{% endblock %}
+    
+    <updated>{{ now|xmldatetime }}</updated>
+    
+    <id>{{ site.full_url }}/</id>
+    
+    {% for node_page in page.node.walk_pages %}
+        {% ifnotequal node_page page %}
+            {% if not node_page.listing and not node_page.exclude %}
+                <entry>
+                    <title type="html">{{ node_page.title }}</title>
+                    <author><name>{{ site.author }}</name></author>
+                    <link href="{{ node_page.full_url }}"/>
+                    <updated>{{ node_page.created|xmldatetime }}</updated>
+                    <published>{{ node_page.created|xmldatetime }}</published>
+                    <id>{{ node_page.full_url }}</id>
+                    {% block entry_extra %}{% endblock %}
+                    <content type="html">
+                        {% filter force_escape %}
+                            {% render_article node_page %}
+                        {% endfilter %}
+                    </content>
+                </entry>
+            {%endif%}
+        {%endifnotequal%}
+    {% endfor %}
+</feed>
+
+{% endspaceless %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/layout/skeleton/_base.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,70 @@
+{% extends "skeleton/_root.html" %}
+
+{% block all %}
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+    <head>
+        <meta http-equiv="content-type" content="text/html; charset=utf-8">
+        
+        <title>{% block title %}{{ page.title|safe }} / {{ site.name }}{% endblock %}</title>
+        
+        {% block feeds %}
+            <link href="{{ site.url }}/blog/atom.xml"
+                  rel="alternate" title="{{ site.name }}"
+                  type="application/atom+xml" />
+        {% endblock %}
+        
+        {% block css %}
+            <link rel="stylesheet"
+                  href="{{ site.url }}/media/css/aal.css"
+                  type="text/css" media="screen" charset="utf-8" />
+            <link rel="stylesheet"
+                  href="{{ site.url }}/media/css/base.css"
+                  type="text/css" media="screen" charset="utf-8" />
+            <link rel="stylesheet"
+                  href="{{ site.url }}/media/css/colorbox.css"
+                  type="text/css" media="screen" charset="utf-8" />
+            {% block extra_css %}{% endblock %}
+        {% endblock %}
+        
+        {% block js %}
+            <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
+            <script src="/media/js/jquery.colorbox.js"></script>
+            <script src="/media/js/sjl-gallery.js"></script>
+            <script src="/mint/?js" type="text/javascript"></script>
+            
+            {% block extra_js %}{% endblock %}
+        {% endblock %}
+    </head>
+    
+    <body>
+        <div id="main-wrap">
+            <div id="header">
+                <h1>
+                    <a href="/">steve losh</a> <span class="page-title">/ {{ page.title|safe|typogrify }}</span>
+                </h1>
+            </div>
+            
+            <div id="nav">
+                <ul>
+                    <li><a href="/blog/">Blog</a></li>
+                    <li><a href="http://bitbucket.org/sjl/">Code</a></li>
+                    <li><a href="/projects">Projects</a></li>
+                    <li><a href="/about/">About</a></li>
+                    <li><a href="/feed/">Feed</a></li>
+                </ul>
+            </div>
+            
+            <div id="content">
+                {% with page.node.ancestors|last as parent_node %}
+                    {% with parent_node.url as parent_url %}
+                        {% block content %}{% endblock %}   
+                    {% endwith %}
+                {% endwith %}
+            </div>
+        </div>
+    </body>
+</html>
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/layout/skeleton/_body.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,7 @@
+{% extends "skeleton/_base.html" %}
+
+{% block title %}{{site.name}} / {{ page.title }}{% endblock %}
+
+{% block content %}
+    {% block content_body %}{% endblock %}
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/layout/skeleton/_index.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,7 @@
+{% extends "skeleton/_base.html" %}
+
+{% block content %}
+    {% for node in page.node.walk %}
+        {% include "skeleton/_innerindex.html" %}
+    {% endfor %} 
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/layout/skeleton/_innerindex.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,27 @@
+{% extends "skeleton/_root.html" %}
+
+{% block all %}
+{%spaceless%}
+{% for list_page in node.pages %}
+    {% ifnotequal list_page node.listing_page %}
+        {% if not list_page.exclude %}
+            <div class="article">
+                <div class="title">
+                    {% with list_page.name_without_extension|remove_date_prefix|unslugify as default_title %}
+                        <h3>
+                            <a href="{{list_page.url}}">
+                                {{ list_page.title|default_if_none:default_title }}
+                            </a>
+                        </h3>
+                        {% if list_page.created %}
+                            <span>{{ list_page.created }}</span>
+                        {% endif %}
+                    {%endwith%}
+                </div>
+                {% render_article list_page %}
+            </div>
+        {%endif%}
+    {% endifnotequal %}
+{% endfor %}
+{%endspaceless%}
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/layout/skeleton/_innerlisting.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,22 @@
+{% extends "skeleton/_root.html" %}
+
+{% block all %}
+{%spaceless%}
+
+{% for list_page in node.pages %}
+    {% ifnotequal list_page node.listing_page %}
+        {% if not list_page.exclude %}
+            <li>
+                <a href="{{ list_page.url }}">
+                    {% with list_page.name_without_extension|remove_date_prefix|unslugify as default_title %}
+                        {{ list_page.title|default_if_none:default_title|safe|typogrify }}
+                    {%endwith%}
+                </a>
+                <span class="snip">{{ list_page.snip|safe|typogrify }}</span>
+            </li>
+        {%endif%}
+    {% endifnotequal %}
+{% endfor %}
+
+{%endspaceless%}
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/layout/skeleton/_listing.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,11 @@
+{% extends "skeleton/_base.html"%}
+
+{% block content %}
+    <div id="section-listing">
+        <ol>
+            {% for node in page.node.walk reversed %}
+                {% include "skeleton/_innerlisting.html" %}
+            {% endfor %}
+        </ol>
+    </div>
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/layout/skeleton/_root.html	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,1 @@
+{% block all %}{% endblock %}
\ No newline at end of file
--- a/manage.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-#!/usr/bin/env python
-from django.core.management import execute_manager
-try:
-    import settings # Assumed to be in the same directory.
-except ImportError:
-    import sys
-    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
-    sys.exit(1)
-
-if __name__ == "__main__":
-    execute_manager(settings)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/media/css/aal.css	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,105 @@
+/* @override http://localhost:8080/media/css/aal.css */
+/* 
+  aardvark.legs by Anatoli Papirovski - http://fecklessmind.com/
+  Licensed under the MIT license. http://www.opensource.org/licenses/mit-license.php
+*/
+
+/*
+  edited for stevelosh.com by Steve Losh
+  changes:
+    base font-size was changed to 14px
+
+/* 
+  Reset first. Modified version of Eric Meyer and Paul Chaplin reset 
+  from http://meyerweb.com/eric/tools/css/reset/ 
+*/
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, font, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+header, nav, section, article, aside, footer
+{border: 0; margin: 0; outline: 0; padding: 0; background: transparent; vertical-align: baseline;}
+
+blockquote, q {quotes: none;}
+blockquote:before,blockquote:after,q:before,q:after {content: ''; content: none;}
+
+header, nav, section, article, aside, footer {display: block;}
+
+/* Basic styles */
+body {background: #fff; color: #000; font: 0.875em/1.5em Helvetica, Arial, "Liberation Sans", "Bitstream Vera Sans", sans-serif;}
+html>body {font-size: 14px;}
+
+img {display: inline-block; vertical-align: bottom;}
+
+h1,h2,h3,h4,h5,h6,strong,b,dt,th {font-weight: 700;}
+address,cite,em,i,caption,dfn,var {font-style: italic;}
+
+h1 {margin: 0 0 0.75em; font-size: 2em;}
+h2 {margin: 0 0 1em; font-size: 1.5em;}
+h3 {margin: 0 0 1.286em; font-size: 1.167em;}
+h4 {margin: 0 0 1.5em; font-size: 1em;}
+h5 {margin: 0 0 1.8em; font-size: .834em;}
+h6 {margin: 0 0 2em; font-size: .75em;}
+
+p,ul,ol,dl,blockquote,pre {margin: 0 0 1.5em;}
+
+li ul,li ol {margin: 0;}
+ul {list-style: outside disc;}
+ol {list-style: outside decimal;}
+li {margin: 0 0 0 3em;}
+dd {padding-left: 1.5em;}
+blockquote {padding: 0 1.5em;}
+
+a {text-decoration: underline;}
+a:hover {text-decoration: none;}
+abbr,acronym {border-bottom: 1px dotted; cursor: help;}
+del {text-decoration: line-through;}
+ins {text-decoration: overline;}
+sub {font-size: .834em; line-height: 1em; vertical-align: sub;}
+sup {font-size: .834em; line-height: 1em; vertical-align: super;}
+
+tt,code,kbd,samp,pre {font-size: 1em; font-family: "Courier New", Courier, monospace;}
+
+/* Table styles */
+table {border-collapse: collapse; border-spacing: 0; margin: 0 0 1.5em;}
+caption {text-align: left;}
+th, td {padding: .25em .5em;}
+tbody td, tbody th {border: 1px solid #000;}
+tfoot {font-style: italic;}
+
+/* Form styles */
+fieldset {clear: both;}
+legend {padding: 0 0 1.286em; font-size: 1.167em; font-weight: 700;}
+fieldset fieldset legend {padding: 0 0 1.5em; font-size: 1em;}
+* html legend {margin-left: -7px;}
+*+html legend {margin-left: -7px;}
+
+form .field, form .buttons {clear: both; margin: 0 0 1.5em;}
+form .field label {display: block;}
+form ul.fields li {list-style-type: none; margin: 0;}
+form ul.inline li, form ul.inline label {display: inline;}
+form ul.inline li {padding: 0 .75em 0 0;}
+
+input.radio, input.checkbox {vertical-align: top;}
+label, button, input.submit, input.image {cursor: pointer;}
+* html input.radio, * html input.checkbox {vertical-align: middle;}
+*+html input.radio, *+html input.checkbox {vertical-align: middle;}
+
+textarea {overflow: auto;}
+input.text, input.password, textarea, select {margin: 0; font: 1em/1.3 Helvetica, Arial, "Liberation Sans", "Bitstream Vera Sans", sans-serif; vertical-align: baseline;}
+input.text, input.password, textarea {border: 1px solid #444; border-bottom-color: #666; border-right-color: #666; padding: 2px;}
+
+* html button {margin: 0 .34em 0 0;}
+*+html button {margin: 0 .34em 0 0;}
+
+form.horizontal .field {padding-left: 150px;}
+form.horizontal .field label {display: inline; float: left; width: 140px; margin-left: -150px;}
+
+/* Useful classes */
+img.left {display: inline; float: left; margin: 0 1.5em .75em 0;}
+img.right {display: inline; float: right; margin: 0 0 .75em .75em;}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/media/css/base.css	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,271 @@
+/* @override http://localhost:8080/media/css/base.css */
+/* Main layout styles. */
+body {
+    font-family: "Helvetica Neue", HelveticaNeue, Arial, Helvetica, sans-serif;
+    color: #111;
+}
+div#main-wrap {
+    width: 62em;
+    margin: 0 auto;
+    margin-bottom: 5em;
+}
+div#content {
+    width: 48em;
+}
+
+/* Link styles. */
+a {
+    text-decoration: none;
+    color: #e50053;
+}
+a:hover {
+    text-decoration: underline;
+}
+h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
+    color: #111;
+}
+h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover {
+    color: #e50053;
+    text-decoration: none;
+}
+
+/* Page header styles. */
+#header {
+    margin-top: 1.5em;
+    margin-bottom: 3em;
+    overflow: visible;
+    white-space: nowrap;
+}
+#header h1 {
+    letter-spacing: -3px;
+    font-size: 3.5em;
+    font-weight: normal;
+    font-family: "Helvetica Neue", HelveticaNeue, Arial, Helvetica, sans-serif;
+    margin-bottom: 0em;
+}
+#header span.page-title {
+    color: #666;
+    text-transform: lowercase;
+}
+
+/* Navigation bar styles. */
+#nav {
+    float: right;
+    width: 10em;
+    font-size: 1.5em;
+    font-weight: bold;
+    line-height: 2em;
+}
+#nav ul li {
+    list-style: none;
+    border-bottom: 1px solid #eee;
+}
+#nav ul li:last-child {
+    border-bottom: none;
+}
+#nav a {
+    border: none;
+    font-style: normal;
+    color: #111;
+}
+#nav a:hover {
+    color: #e50053;
+    text-decoration: none;
+}
+
+/* Splash page styles. */
+#splash-info {
+    font-size: 1.5em;
+    line-height: 2em;
+    text-align: right;
+    color: #888;
+    font-family: "Helvetica Neue Light", HelveticaNeue-Light, Arial, Helvetica, sans-serif;
+}
+#splash-info ul li {
+    margin: 0;
+    list-style: none;
+    border-bottom: 1px solid #eee;
+}
+#splash-info ul li:last-child {
+    border-bottom: none;
+}
+
+/* Section listing styles. */
+div#section-listing {
+    font-size: 1.5em;
+    font-weight: bold;
+    line-height: 2em;
+    color: #888;
+}
+div#section-listing ol {
+    list-style: none;
+}
+div#section-listing ol li {
+    border-bottom: 1px solid #eee;
+    margin: 0;
+}
+div#section-listing ol a {
+    color: #111;
+}
+div#section-listing ol a:hover {
+    color: #e50053;
+    text-decoration: none;
+}
+div#section-listing ol li:last-child {
+    border-bottom: none;
+}
+div#section-listing ol li span.snip {
+    font-size: 0.65em;
+    line-height: 1em;
+    margin-left: 0.5em;
+    font-weight: normal;
+}
+
+/* Code styles. */
+code, pre {
+    font-family: Consolas, Monaco, "Courier New", monospace;
+    font-size: 12px;
+    line-height: 21px;
+}
+p code, li code {
+    border: 1px solid #ccc;
+    background-color: #fafafa;
+    padding: 1px 3px;
+}
+pre {
+    border: 1px solid #ccc;
+    background-color: #fafafa;
+    padding: 0px 5px;
+    margin-left: 2em;
+    overflow: auto;
+}
+
+/* Quoting styles. */
+blockquote {
+    border: 1px solid #ccc;
+    background-color: #fafafa;
+    padding: 0px 5px;
+    margin-left: 2em;
+    overflow: auto;
+}
+blockquote p:last-child {
+    margin-bottom: 0;
+}
+span.dquo {
+    margin-left: -0.23em;
+}
+
+/* Table of Contents styles. */
+div.toc ul {
+    list-style: none;
+}
+div.toc ul:first-child>li {
+    margin-left: 0em;
+}
+
+/* Ampersand styles. */
+span.amp {
+    font-family: "Palatino", "Constantia", "Palatino Linotype", serif;
+    font-style: italic;
+}
+div#section-listing ol li a span.amp {
+    font-weight: bold;
+    line-height: 0.85em;
+    font-size: 1.1em;
+    color: inherit;
+}
+h1 span.amp, h2 span.amp, h3 span.amp, h4 span.amp, h5 span.amp, h6 span.amp {
+    font-weight: bold;
+    line-height: 0.5em;
+    font-size: 1.1em;
+    color: inherit;
+    
+}
+span.page-title span.amp {
+    font-weight: normal;
+    font-size: 1em;
+    line-height: 0.5em;
+}
+
+/* Article styles. */
+div#leaf-stats p {
+    color: #666;
+    margin-top: -1em;
+    margin-bottom: 1em;
+}
+
+/* Image styles. */
+div#leaf-content img {
+    display: block;
+    margin-left: auto;
+    margin-right: auto;
+    border: 1.43em solid #e5e5e5;
+    padding: 1px;
+    background: black;
+}
+div#leaf-content img.left, div#leaf-content img.right {
+    border: none;
+    background: none;
+    padding: none;
+}
+div#leaf-content img.left {
+     margin: 0 1.5em 1em 0;
+}
+div#leaf-content img.right {
+    margin: 0 0 .75em 1em;
+}
+div#leaf-content div.gallery img {
+    background: none;
+    padding: 0;
+    border: none;
+    display: inline;
+    margin-bottom: 1.5em;
+    margin-right: 1.5em;
+}
+div#leaf-content div.with-diagrams img {
+    display: block;
+    margin-left: auto;
+    margin-right: auto;
+    background: none;
+    border: none;
+}
+
+/* Comment styles. */
+h1#comment-header {
+    margin-top: 1.5em;
+}
+div#disqus_thread ul#dsq-comments li div div {
+    font-size: 14px;
+}
+div#disqus_thread ul#dsq-comments li {
+    margin-bottom: 2em;
+}
+div#dsq-comments-title h3 {
+    font-size: 14px;
+    font-weight: normal;
+    color: #666;
+    margin-top: -1em;
+    margin-bottom: 1em;
+}
+div.dsq-options {
+    display: none;
+}
+div#content div#disqus_thread ul#dsq-comments li div table tbody tr {
+    background: #eee;
+}
+div#content div#disqus_thread ul#dsq-comments li div table {
+    background: #e5e5e5;
+    border: 1px solid #bbb;
+}
+div#dsq-new-post.dsq-post-area {
+    margin-top: 2.25em;
+}
+div#dsq-thread-settings.dsq-thread-settings {
+    margin-top: 2em;
+    margin-bottom: 0em;
+    font-size: 14px;
+}
+div#disqus_thread table tbody tr td.dsq-request-user-name small,
+#dsq-new-post div.dsq-request-user-info a {
+    font-size: 14px;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/media/css/colorbox.css	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,50 @@
+/*
+    ColorBox Core Style
+    The following rules are the styles that are consistant between themes.
+    Avoid changing this area to maintain compatability with future versions of ColorBox.
+*/
+#colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden;}
+#cboxOverlay{position:fixed; width:100%; height:100%;}
+#cboxMiddleLeft, #cboxBottomLeft{clear:left;}
+#cboxContent{position:relative; overflow:visible;}
+#cboxLoadedContent{overflow:auto;}
+#cboxLoadedContent iframe{display:block; width:100%; height:100%; border:0;}
+#cboxTitle{margin:0;}
+#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%;}
+#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;}
+
+/* 
+    ColorBox example user style
+    The following rules are ordered and tabbed in a way that represents the
+    order/nesting of the generated HTML, so that the structure easier to understand.
+*/
+#cboxOverlay{background:#000;}
+
+#colorbox{}
+    #cboxTopLeft{width:14px; height:14px; background:url(/media/images/colorbox/controls.png) 0 0 no-repeat;}
+    #cboxTopCenter{height:14px; background:url(/media/images/colorbox/border.png) top left repeat-x;}
+    #cboxTopRight{width:14px; height:14px; background:url(/media/images/colorbox/controls.png) -36px 0 no-repeat;}
+    #cboxBottomLeft{width:14px; height:43px; background:url(/media/images/colorbox/controls.png) 0 -32px no-repeat;}
+    #cboxBottomCenter{height:43px; background:url(/media/images/colorbox/border.png) bottom left repeat-x;}
+    #cboxBottomRight{width:14px; height:43px; background:url(/media/images/colorbox/controls.png) -36px -32px no-repeat;}
+    #cboxMiddleLeft{width:14px; background:url(/media/images/colorbox/controls.png) -175px 0 repeat-y;}
+    #cboxMiddleRight{width:14px; background:url(/media/images/colorbox/controls.png) -211px 0 repeat-y;}
+    #cboxContent{background:#fff;}
+        #cboxLoadedContent{margin-bottom:5px;}
+        #cboxLoadingOverlay{background:url(/media/images/colorbox/loading_background.png) center center no-repeat;}
+        #cboxLoadingGraphic{background:url(/media/images/colorbox/loading.gif) center center no-repeat;}
+        #cboxTitle{position:absolute; bottom:-25px; left:0; text-align:center; width:100%; font-weight:bold; color:#7C7C7C;}
+        #cboxCurrent{position:absolute; bottom:-25px; left:58px; font-weight:bold; color:#7C7C7C;}
+        
+        #cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{position:absolute; bottom:-29px; background:url(/media/images/colorbox/controls.png) 0px 0px no-repeat; width:23px; height:23px; text-indent:-9999px;}
+        #cboxPrevious{left:0px; background-position: -51px -25px;}
+        #cboxPrevious.hover{background-position:-51px 0px;}
+        #cboxNext{left:27px; background-position:-75px -25px;}
+        #cboxNext.hover{background-position:-75px 0px;}
+        #cboxClose{right:0; background-position:-100px -25px;}
+        #cboxClose.hover{background-position:-100px 0px;}
+        
+        .cboxSlideshow_on #cboxSlideshow{background-position:-125px 0px; right:27px;}
+        .cboxSlideshow_on #cboxSlideshow.hover{background-position:-150px 0px;}
+        .cboxSlideshow_off #cboxSlideshow{background-position:-150px -25px; right:27px;}
+        .cboxSlideshow_off #cboxSlideshow.hover{background-position:-125px 0px;}
\ No newline at end of file
Binary file media/images/blog/2009/02/dj-playlist-sorting.png has changed
Binary file media/images/blog/2009/02/dj-playlist-unrated.png has changed
Binary file media/images/blog/2009/03/prompt-with-branch.png has changed
Binary file media/images/blog/2009/03/prompt-with-dirty.png has changed
Binary file media/images/blog/2009/03/prompt-without-branch.png has changed
Binary file media/images/blog/2009/03/terminal-colors.png has changed
Binary file media/images/blog/2009/08/branch-anon.png has changed
Binary file media/images/blog/2009/08/branch-base.png has changed
Binary file media/images/blog/2009/08/branch-bookmark.png has changed
Binary file media/images/blog/2009/08/branch-clone.png has changed
Binary file media/images/blog/2009/08/branch-named.png has changed
Binary file media/images/colorbox/border.png has changed
Binary file media/images/colorbox/controls.png has changed
Binary file media/images/colorbox/loading.gif has changed
Binary file media/images/colorbox/loading_background.png has changed
Binary file media/images/projects/fuego/Fuego-4852.jpg has changed
Binary file media/images/projects/fuego/Fuego-4887.jpg has changed
Binary file media/images/projects/fuego/Fuego-4919.jpg has changed
Binary file media/images/projects/fuego/Fuego-4941.jpg has changed
Binary file media/images/projects/fuego/Fuego-4985.jpg has changed
Binary file media/images/projects/fuego/Fuego-5133.jpg has changed
Binary file media/images/projects/hg-prompt/prompt.png has changed
Binary file media/images/projects/lindyjam-com/lindyjamcom-splash.png has changed
Binary file media/images/projects/women-in-water/alex-tele.jpg has changed
Binary file media/images/projects/women-in-water/alex-wide.jpg has changed
Binary file media/images/projects/women-in-water/anna-tele.jpg has changed
Binary file media/images/projects/women-in-water/anna-wide.jpg has changed
Binary file media/images/projects/women-in-water/erin-tele.jpg has changed
Binary file media/images/projects/women-in-water/erin-wide.jpg has changed
Binary file media/images/projects/women-in-water/leah-tele.jpg has changed
Binary file media/images/projects/women-in-water/leah-wide.jpg has changed
Binary file media/images/projects/women-in-water/lizza-tele.jpg has changed
Binary file media/images/projects/women-in-water/lizza-wide.jpg has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/media/js/jquery.colorbox.js	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,752 @@
+// ColorBox v1.3.5 - a full featured, light-weight, customizable lightbox based on jQuery 1.3
+// c) 2009 Jack Moore - www.colorpowered.com - jack@colorpowered.com
+// Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+(function ($) {
+	// Shortcuts (to increase compression)
+	var colorbox = 'colorbox',
+	hover = 'hover',
+	TRUE = true,
+	FALSE = false,
+	cboxPublic,
+	isIE = !$.support.opacity,
+	isIE6 = isIE && !window.XMLHttpRequest,
+
+	// Event Strings (to increase compression)
+	cbox_open = 'cbox_open',
+	cbox_load = 'cbox_load',
+	cbox_complete = 'cbox_complete',
+	cbox_cleanup = 'cbox_cleanup',
+	cbox_closed = 'cbox_closed',
+	cbox_resize = 'resize.cbox_resize',
+
+	// Cached jQuery Object Variables
+	$overlay,
+	$cbox,
+	$wrap,
+	$content,
+	$topBorder,
+	$leftBorder,
+	$rightBorder,
+	$bottomBorder,
+	$related,
+	$window,
+	$loaded,
+	$loadingBay,
+	$loadingOverlay,
+	$loadingGraphic,
+	$title,
+	$current,
+	$slideshow,
+	$next,
+	$prev,
+	$close,
+
+	// Variables for cached values or use across multiple functions
+	interfaceHeight,
+	interfaceWidth,
+	loadedHeight,
+	loadedWidth,
+	element,
+	bookmark,
+	index,
+	settings,
+	open,
+	active,
+	
+	// ColorBox Default Settings.	
+	// See http://colorpowered.com/colorbox for details.
+	defaults = {
+		transition: "elastic",
+		speed: 350,
+		width: FALSE,
+		height: FALSE,
+		innerWidth: FALSE,
+		innerHeight: FALSE,
+		initialWidth: "400",
+		initialHeight: "400",
+		maxWidth: FALSE,
+		maxHeight: FALSE,
+		scalePhotos: TRUE,
+		scrolling: TRUE,
+		inline: FALSE,
+		html: FALSE,
+		iframe: FALSE,
+		photo: FALSE,
+		href: FALSE,
+		title: FALSE,
+		rel: FALSE,
+		opacity: 0.9,
+		preloading: TRUE,
+		current: "image {current} of {total}",
+		previous: "previous",
+		next: "next",
+		close: "close",
+		open: FALSE,
+		overlayClose: TRUE,
+		
+		slideshow: FALSE,
+		slideshowAuto: TRUE,
+		slideshowSpeed: 2500,
+		slideshowStart: "start slideshow",
+		slideshowStop: "stop slideshow",
+		
+		onOpen: FALSE,
+		onLoad: FALSE,
+		onComplete: FALSE,
+		onCleanup: FALSE,
+		onClosed: FALSE
+	};
+	
+	// ****************
+	// HELPER FUNCTIONS
+	// ****************
+		
+	// Convert % values to pixels
+	function setSize(size, dimension) {
+		dimension = dimension === 'x' ? $window.width() : $window.height();//document.documentElement.clientWidth : document.documentElement.clientHeight;
+		return (typeof size === 'string') ? Math.round((size.match(/%/) ? (dimension / 100) * parseInt(size, 10) : parseInt(size, 10))) : size;
+	}
+
+	// Checks an href to see if it is a photo.
+	// There is a force photo option (photo: true) for hrefs that cannot be matched by this regex.
+	function isImage(url) {
+		url = $.isFunction(url) ? url.call(element) : url;
+		return settings.photo || url.match(/\.(gif|png|jpg|jpeg|bmp)(?:\?([^#]*))?(?:#(\.*))?$/i);
+	}
+	
+	// Assigns functions results to their respective settings.  This allows functions to be used to set ColorBox options.
+	function process() {
+		for (var i in settings) {
+			if ($.isFunction(settings[i]) && i.substring(0, 2) !== 'on') { // checks to make sure the function isn't one of the callbacks, they will be handled at the appropriate time.
+			    settings[i] = settings[i].call(element);
+			}
+		}
+	}
+
+	function launch(elem) {
+		
+		element = elem;
+		
+		settings = $(element).data(colorbox);
+		
+		process(); // Convert functions to their returned values.
+		
+		var rel = settings.rel || element.rel;
+		
+		if (rel && rel !== 'nofollow') {
+			$related = $('.cboxElement').filter(function () {
+				var relRelated = $(this).data(colorbox).rel || this.rel;
+				return (relRelated === rel);
+			});
+			index = $related.index(element);
+			
+			// Check direct calls to ColorBox.
+			if (index < 0) {
+				$related = $related.add(element);
+				index = $related.length - 1;
+			}
+		} else {
+			$related = $(element);
+			index = 0;
+		}
+		
+		if (!open) {
+			open = TRUE;
+			
+			active = TRUE; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys.
+			
+			bookmark = element;
+			
+			bookmark.blur(); // Remove the focus from the calling element.
+			
+			// Set Navigation Key Bindings
+			$().bind("keydown.cbox_close", function (e) {
+				if (e.keyCode === 27) {
+					e.preventDefault();
+					cboxPublic.close();
+				}
+			}).bind("keydown.cbox_arrows", function (e) {
+				if ($related.length > 1) {
+					if (e.keyCode === 37) {
+						e.preventDefault();
+						$prev.click();
+					} else if (e.keyCode === 39) {
+						e.preventDefault();
+						$next.click();
+					}
+				}
+			});
+			
+			if (settings.overlayClose) {
+				$overlay.css({"cursor": "pointer"}).one('click', cboxPublic.close);
+			}
+			
+			$.event.trigger(cbox_open);
+			if (settings.onOpen) {
+				settings.onOpen.call(element);
+			}
+			
+			$overlay.css({"opacity": settings.opacity}).show();
+			
+			// Opens inital empty ColorBox prior to content being loaded.
+			settings.w = setSize(settings.initialWidth, 'x');
+			settings.h = setSize(settings.initialHeight, 'y');
+			cboxPublic.position(0);
+			
+			if (isIE6) {
+				$window.bind('resize.cboxie6 scroll.cboxie6', function () {
+					$overlay.css({width: $window.width(), height: $window.height(), top: $window.scrollTop(), left: $window.scrollLeft()});
+				}).trigger("scroll.cboxie6");
+			}
+		}
+		
+		$current.add($prev).add($next).add($slideshow).add($title).hide();
+		
+		$close.html(settings.close).show();
+		
+		cboxPublic.slideshow();
+		
+		cboxPublic.load();
+	}
+
+	// ****************
+	// PUBLIC FUNCTIONS
+	// Usage format: $.fn.colorbox.close();
+	// Usage from within an iframe: parent.$.fn.colorbox.close();
+	// ****************
+	
+	cboxPublic = $.fn.colorbox = function (options, callback) {
+		var $this = this;
+		
+		if (!$this.length) {
+			if ($this.selector === '') { // empty selector means a direct call, ie: $.fn.colorbox();
+				$this = $($this);
+				options.open = TRUE;
+			} else { // else the selector didn't match anything, and colorbox should go ahead and return.
+				return this;
+			}
+		}
+		
+		$this.each(function () {
+			var data = $.extend({}, $(this).data(colorbox) ? $(this).data(colorbox) : defaults, options);
+			
+			$(this).data(colorbox, data).addClass("cboxElement");
+			
+			if (callback) {
+				$(this).data(colorbox).onComplete = callback;
+			}
+		});
+		
+		if (options && options.open) {
+			launch($this);
+		}
+		
+		return this;
+	};
+
+	// Initialize ColorBox: store common calculations, preload the interface graphics, append the html.
+	// This preps colorbox for a speedy open when clicked, and lightens the burdon on the browser by only
+	// having to run once, instead of each time colorbox is opened.
+	cboxPublic.init = function () {
+		
+		// jQuery object generator to save a bit of space
+		function $div(id) {
+			return $('<div id="cbox' + id + '"/>');
+		}
+		
+		// Create & Append jQuery Objects
+		$window = $(window);
+		$cbox = $('<div id="colorbox"/>');
+		$overlay = $div("Overlay").hide();
+		$wrap = $div("Wrapper");
+		$content = $div("Content").append(
+			$loaded = $div("LoadedContent").css({width: 0, height: 0}),
+			$loadingOverlay = $div("LoadingOverlay"),
+			$loadingGraphic = $div("LoadingGraphic"),
+			$title = $div("Title"),
+			$current = $div("Current"),
+			$slideshow = $div("Slideshow"),
+			$next = $div("Next"),
+			$prev = $div("Previous"),
+			$close = $div("Close")
+		);
+		$wrap.append( // The 3x3 Grid that makes up ColorBox
+			$('<div/>').append(
+				$div("TopLeft"),
+				$topBorder = $div("TopCenter"),
+				$div("TopRight")
+			),
+			$('<div/>').append(
+				$leftBorder = $div("MiddleLeft"),
+				$content,
+				$rightBorder = $div("MiddleRight")
+			),
+			$('<div/>').append(
+				$div("BottomLeft"),
+				$bottomBorder = $div("BottomCenter"),
+				$div("BottomRight")
+			)
+		).children().children().css({'float': 'left'});
+		
+		$loadingBay = $("<div style='position:absolute; top:0; left:0; width:9999px; height:0;'/>");
+		
+		$('body').prepend($overlay, $cbox.append($wrap, $loadingBay));
+				
+		if (isIE) {
+			$cbox.addClass('cboxIE');
+			if (isIE6) {
+				$overlay.css('position', 'absolute');
+			}
+		}
+		
+		// Add rollover event to navigation elements
+		$content.children()
+		.addClass(hover)
+		.mouseover(function () { $(this).addClass(hover); })
+		.mouseout(function () { $(this).removeClass(hover); });
+		
+		// Cache values needed for size calculations
+		interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(TRUE) - $content.height();//Subtraction needed for IE6
+		interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(TRUE) - $content.width();
+		loadedHeight = $loaded.outerHeight(TRUE);
+		loadedWidth = $loaded.outerWidth(TRUE);
+		
+		// Setting padding to remove the need to do size conversions during the animation step.
+		$cbox.css({"padding-bottom": interfaceHeight, "padding-right": interfaceWidth}).hide();
+		
+		// Setup button & key events.
+		$next.click(cboxPublic.next);
+		$prev.click(cboxPublic.prev);
+		$close.click(cboxPublic.close);
+		
+		// Adding the 'hover' class allowed the browser to load the hover-state
+		// background graphics.  The class can now can be removed.
+		$content.children().removeClass(hover);
+		
+		$('.cboxElement').live('click', function (e) {
+			if (e.button !== 0 && typeof e.button !== 'undefined') {// checks to see if it was a non-left mouse-click.
+				return TRUE;
+			} else {
+				launch(this);			
+				return FALSE;
+			}
+		});
+	};
+
+	cboxPublic.position = function (speed, loadedCallback) {
+		var
+		animate_speed,
+		winHeight = $window.height(),
+		// keeps the top and left positions within the browser's viewport.
+		posTop = Math.max(winHeight - settings.h - loadedHeight - interfaceHeight,0)/2 + $window.scrollTop(),
+		posLeft = Math.max(document.documentElement.clientWidth - settings.w - loadedWidth - interfaceWidth,0)/2 + $window.scrollLeft();
+		
+		// setting the speed to 0 to reduce the delay between same-sized content.
+		animate_speed = ($cbox.width() === settings.w+loadedWidth && $cbox.height() === settings.h+loadedHeight) ? 0 : speed;
+		
+		// this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly,
+		// but it has to be shrank down around the size of div#colorbox when it's done.  If not,
+		// it can invoke an obscure IE bug when using iframes.
+		$wrap[0].style.width = $wrap[0].style.height = "9999px";
+		
+		function modalDimensions (that) {
+			// loading overlay size has to be sure that IE6 uses the correct height.
+			$topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = that.style.width;
+			$loadingGraphic[0].style.height = $loadingOverlay[0].style.height = $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = that.style.height;
+		}
+		
+		$cbox.dequeue().animate({width:settings.w+loadedWidth, height:settings.h+loadedHeight, top:posTop, left:posLeft}, {duration: animate_speed,
+			complete: function(){
+				modalDimensions(this);
+				
+				active = FALSE;
+				
+				// shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation.
+				$wrap[0].style.width = (settings.w+loadedWidth+interfaceWidth) + "px";
+				$wrap[0].style.height = (settings.h+loadedHeight+interfaceHeight) + "px";
+				
+				if (loadedCallback) {loadedCallback();}
+			},
+			step: function(){
+				modalDimensions(this);
+			}
+		});
+	};
+
+	cboxPublic.resize = function (object) {
+		if(!open){ return; }
+		
+		var topMargin,
+		prev,
+		prevSrc,
+		next,
+		nextSrc,
+		photo,
+		timeout,
+		speed = settings.transition==="none" ? 0 : settings.speed;
+		
+		$window.unbind(cbox_resize);
+		
+		if(!object){
+			timeout = setTimeout(function(){ // timer allows IE to render the dimensions before attempting to calculate the height
+				var $child = $loaded.wrapInner("<div style='overflow:auto'></div>").children(); // temporary wrapper to get an accurate estimate of just how high the total content should be.
+				settings.h = $child.height();
+				$loaded.css({height:settings.h});
+				$child.replaceWith($child.children()); // ditch the temporary wrapper div used in height calculation
+				cboxPublic.position(speed);
+			}, 1);
+			return;
+		}
+		
+		$loaded.remove();
+		$loaded = $('<div id="cboxLoadedContent"/>').html(object);
+		
+		function getWidth(){
+			settings.w = settings.w || $loaded.width();
+			settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w;
+			return settings.w;
+		}
+		function getHeight(){
+			settings.h = settings.h || $loaded.height();
+			settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h;
+			return settings.h;
+		}
+		
+		$loaded.hide()
+		.appendTo($loadingBay)// content has to be appended to the DOM for accurate size calculations.  Appended to an absolutely positioned element, rather than BODY, which avoids an extremely brief display of the vertical scrollbar in Firefox that can occur for a small minority of websites.
+		.css({width:getWidth(), overflow:settings.scrolling ? 'auto' : 'hidden'})
+		.css({height:getHeight()})// sets the height independently from the width in case the new width influences the value of height.
+		.prependTo($content);
+		
+		$('#cboxPhoto').css({cssFloat:'none'});// floating the IMG removes the bottom line-height and fixed a problem where IE miscalculates the width of the parent element as 100% of the document width.
+		
+		// Hides SELECT elements in IE6 because they would otherwise sit on top of the overlay.
+		if (isIE6) {
+			$('select:not(#colorbox select)').filter(function(){
+				return this.style.visibility !== 'hidden';
+			}).css({'visibility':'hidden'}).one(cbox_cleanup, function(){
+				this.style.visibility = 'inherit';
+			});
+		}
+				
+		function setPosition (s) {
+			cboxPublic.position(s, function(){
+				if (!open) { return; }
+				
+				if (isIE) {
+					//This fadeIn helps the bicubic resampling to kick-in.
+					if( photo ){$loaded.fadeIn(100);}
+					//IE adds a filter when ColorBox fades in and out that can cause problems if the loaded content contains transparent pngs.
+					$cbox[0].style.removeAttribute("filter");
+				}
+				
+				//Waited until the iframe is added to the DOM & it is visible before setting the src.
+				//This increases compatability with pages using DOM dependent JavaScript.
+				if(settings.iframe){
+					$loaded.append("<iframe id='cboxIframe'" + (settings.scrolling ? " " : "scrolling='no'") + " name='iframe_"+new Date().getTime()+"' frameborder=0 src='"+(settings.href || element.href)+"' " + (isIE ? "allowtransparency='true'" : '') + " />");
+				}
+				
+				$loaded.show();
+				
+				$title.html(settings.title || element.title);
+				
+				$title.show();
+				
+				if ($related.length>1) {
+					$current.html(settings.current.replace(/\{current\}/, index+1).replace(/\{total\}/, $related.length)).show();
+					$next.html(settings.next).show();
+					$prev.html(settings.previous).show();
+					
+					if(settings.slideshow){
+						$slideshow.show();
+					}
+				}
+				
+				$loadingOverlay.hide();
+				$loadingGraphic.hide();
+				
+				$.event.trigger(cbox_complete);
+				if (settings.onComplete) {
+					settings.onComplete.call(element);
+				}
+				
+				if (settings.transition === 'fade'){
+					$cbox.fadeTo(speed, 1, function(){
+						if(isIE){$cbox[0].style.removeAttribute("filter");}
+					});
+				}
+				
+				$window.bind(cbox_resize, function(){
+					cboxPublic.position(0);
+				});
+			});
+		}
+		
+		if((settings.transition === 'fade' && $cbox.fadeTo(speed, 0, function(){setPosition(0);})) || setPosition(speed)){}
+		
+		// Preloads images within a rel group
+		if (settings.preloading && $related.length>1) {
+			prev = index > 0 ? $related[index-1] : $related[$related.length-1];
+			next = index < $related.length-1 ? $related[index+1] : $related[0];
+			nextSrc = $(next).data(colorbox).href || next.href;
+			prevSrc = $(prev).data(colorbox).href || prev.href;
+			
+			if(isImage(nextSrc)){
+				$('<img />').attr('src', nextSrc);
+			}
+			
+			if(isImage(prevSrc)){
+				$('<img />').attr('src', prevSrc);
+			}
+		}
+	};
+
+	cboxPublic.load = function () {
+		var href, img, setResize, resize = cboxPublic.resize;
+		
+		active = TRUE;
+		
+		/*
+		 
+		// I decided to comment this out because I can see it causing problems as users
+		// really should just set the dimensions on their IMG elements instead,
+		// but I'm leaving the code in as it may be useful to someone.
+		// To use, uncomment the function and change 'if(textStatus === "success"){ resize(this); }'
+		// to 'if(textStatus === "success"){ preload(this); }'
+		
+		// Preload loops through the HTML to find IMG elements and loads their sources.
+		// This allows the resize method to accurately estimate the dimensions of the new content.
+		function preload(html){
+			var
+			$ajax = $(html),
+			$imgs = $ajax.find('img'),
+			x = $imgs.length;
+			
+			function loadloop(){
+				var img = new Image();
+				x = x-1;
+				if(x >= 0){
+					img.onload = loadloop;
+					img.src = $imgs[x].src;
+				} else {
+					resize($ajax);
+				}
+			}
+			
+			loadloop();
+		}
+		*/
+		
+		element = $related[index];
+		
+		settings = $(element).data(colorbox);
+		
+		//convert functions to static values
+		process();
+		
+		$.event.trigger(cbox_load);
+		if (settings.onLoad) {
+			settings.onLoad.call(element);
+		}
+		
+		// Evaluate the height based on the optional height and width settings.
+		settings.h = settings.height ?
+				setSize(settings.height, 'y') - loadedHeight - interfaceHeight :
+				settings.innerHeight ?
+					setSize(settings.innerHeight, 'y') :
+					FALSE;
+		settings.w = settings.width ?
+				setSize(settings.width, 'x') - loadedWidth - interfaceWidth :
+				settings.innerWidth ?
+					setSize(settings.innerWidth, 'x') :
+					FALSE;
+		
+		// Sets the minimum dimensions for use in image scaling
+		settings.mw = settings.w;
+		settings.mh = settings.h;
+		
+		// Re-evaluate the minimum width and height based on maxWidth and maxHeight values.
+		// If the width or height exceed the maxWidth or maxHeight, use the maximum values instead.
+		if(settings.maxWidth){
+			settings.mw = setSize(settings.maxWidth, 'x') - loadedWidth - interfaceWidth;
+			settings.mw = settings.w && settings.w < settings.mw ? settings.w : settings.mw;
+		}
+		if(settings.maxHeight){
+			settings.mh = setSize(settings.maxHeight, 'y') - loadedHeight - interfaceHeight;
+			settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh;
+		}
+		
+		href = settings.href || $(element).attr("href");
+		
+		$loadingOverlay.show();
+		$loadingGraphic.show();
+		
+		if (settings.inline) {
+			// Inserts an empty placeholder where inline content is being pulled from.
+			// An event is bound to put inline content back when ColorBox closes or loads new content.
+			$('<div id="cboxInlineTemp" />').hide().insertBefore($(href)[0]).bind(cbox_load+' '+cbox_cleanup, function(){
+				$(this).replaceWith($loaded.children());
+			});
+			resize($(href));
+		} else if (settings.iframe) {
+			// IFrame element won't be added to the DOM until it is ready to be displayed,
+			// to avoid problems with DOM-ready JS that might be trying to run in that iframe.
+			resize(" ");
+		} else if (settings.html) {
+			resize(settings.html);
+		} else if (isImage(href)){
+			img = new Image();
+			img.onload = function(){
+				var percent;
+				
+				img.onload = null;
+				
+				img.id = 'cboxPhoto';
+				
+				$(img).css({margin:'auto', border:'none', display:'block', cssFloat:'left'});
+				
+				if(settings.scalePhotos){
+					setResize = function(){
+						img.height -= img.height * percent;
+						img.width -= img.width * percent;	
+					};
+					if(settings.mw && img.width > settings.mw){
+						percent = (img.width - settings.mw) / img.width;
+						setResize();
+					}
+					if(settings.mh && img.height > settings.mh){
+						percent = (img.height - settings.mh) / img.height;
+						setResize();
+					}
+				}
+				
+				if (settings.h) {
+					img.style.marginTop = Math.max(settings.h - img.height,0)/2 + 'px';
+				}
+				
+				resize(img);
+				
+				if($related.length > 1){
+					$(img).css({cursor:'pointer'}).click(cboxPublic.next);
+				}
+				
+				if(isIE){
+					img.style.msInterpolationMode='bicubic';
+				}
+			};
+			img.src = href;
+		} else {
+			$('<div />').appendTo($loadingBay).load(href, function(data, textStatus){
+				if(textStatus === "success"){
+					resize(this);
+				} else {
+					resize($("<p>Request unsuccessful.</p>"));
+				}
+			});
+		}
+	};
+
+	// Navigates to the next page/image in a set.
+	cboxPublic.next = function () {
+		if(!active){
+			index = index < $related.length-1 ? index+1 : 0;
+			cboxPublic.load();
+		}
+	};
+	
+	cboxPublic.prev = function () {
+		if(!active){
+			index = index > 0 ? index-1 : $related.length-1;
+			cboxPublic.load();
+		}
+	};
+
+	cboxPublic.slideshow = function () {
+		var stop, timeOut, className = 'cboxSlideshow_';
+		
+		$slideshow.bind(cbox_closed, function(){
+			$slideshow.unbind();
+			clearTimeout(timeOut);
+			$cbox.removeClass(className+"off"+" "+className+"on");
+		});
+		
+		function start(){
+			$slideshow
+			.text(settings.slideshowStop)
+			.bind(cbox_complete, function(){
+				timeOut = setTimeout(cboxPublic.next, settings.slideshowSpeed);
+			})
+			.bind(cbox_load, function(){
+				clearTimeout(timeOut);	
+			}).one("click", function(){
+				stop();
+				$(this).removeClass(hover);
+			});
+			$cbox.removeClass(className+"off").addClass(className+"on");
+		}
+		
+		stop = function(){
+			clearTimeout(timeOut);
+			$slideshow
+			.text(settings.slideshowStart)
+			.unbind(cbox_complete+' '+cbox_load)
+			.one("click", function(){
+				start();
+				timeOut = setTimeout(cboxPublic.next, settings.slideshowSpeed);
+				$(this).removeClass(hover);
+			});
+			$cbox.removeClass(className+"on").addClass(className+"off");
+		};
+		
+		if(settings.slideshow && $related.length>1){
+			if(settings.slideshowAuto){
+				start();
+			} else {
+				stop();
+			}
+		}
+	};
+
+	// Note: to use this within an iframe use the following format: parent.$.fn.colorbox.close();
+	cboxPublic.close = function () {
+		
+		$.event.trigger(cbox_cleanup);
+		if (settings.onCleanup) {
+			settings.onCleanup.call(element);
+		}
+		
+		open = FALSE;
+		$().unbind("keydown.cbox_close keydown.cbox_arrows");
+		$window.unbind(cbox_resize+' resize.cboxie6 scroll.cboxie6');
+		$overlay.css({cursor: 'auto'}).fadeOut('fast');
+		
+		$cbox
+		.stop(TRUE, FALSE)
+		.fadeOut('fast', function () {
+			$loaded.remove();
+			$cbox.css({'opacity': 1});
+			
+			try{
+				bookmark.focus();
+			} catch (er){
+				// do nothing
+			}
+			
+			$.event.trigger(cbox_closed);
+			if (settings.onClosed) {
+				settings.onClosed.call(element);
+			}
+		});
+	};
+
+	// A method for fetching the current element ColorBox is referencing.
+	// returns a jQuery object.
+	cboxPublic.element = function(){ return $(element); };
+
+	cboxPublic.settings = defaults;
+
+	// Initializes ColorBox when the DOM has loaded
+	$(cboxPublic.init);
+
+}(jQuery));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/media/js/sjl-gallery.js	Sat Jan 09 04:01:49 2010 -0500
@@ -0,0 +1,3 @@
+$(function() {
+    $("div.gallery a").colorbox();
+});
\ No newline at end of file
--- a/projects/admin.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-from stevelosh.projects.models import Project, Comment
-from django.contrib import admin
-
-class ProjectAdmin(admin.ModelAdmin):
-    list_display = ('name', 'snip', 'type', 'posted',)
-    search_fields = ('name', 'snip', 'body')
-    list_filter = ('type',)
-    date_hierarchy = 'posted'
-    ordering = ('-posted',)
-    prepopulated_fields = { 'slug': ('name',) }
-
-class CommentAdmin(admin.ModelAdmin):
-    fields = ('name', 'body', 'submitted', 'project', 'spam')
-    list_display = ('project', 'name', 'submitted', 'snip', 'spam')
-    search_fields = ('name', 'body')
-    list_filter = ('name', 'project', 'spam')
-    date_hierarchy = 'submitted'
-    ordering = ('-submitted',)
-
-
-admin.site.register(Project, ProjectAdmin)
-admin.site.register(Comment, CommentAdmin)
--- a/projects/models.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-from django.db import models
-import datetime
-
-
-class Project(models.Model):
-    """A model of a project."""
-    
-    name = models.CharField(blank=False, max_length=140)
-    snip = models.CharField(blank=False, max_length=140)
-    type = models.CharField(blank=True, max_length=15)
-    body = models.TextField(blank=True)
-    posted = models.DateTimeField(blank=False, default=datetime.datetime.now)
-    slug = models.SlugField()
-    
-    def get_absolute_url(self):
-        return u'/projects/%s/' % (self.slug,)
-    
-    def __unicode__(self):
-        return u"%s" % (self.name,)
-
-
-class Comment(models.Model):
-    name = models.CharField(blank=False, null=False, max_length=40)
-    body = models.TextField(blank=False, null=False)
-    submitted = models.DateTimeField(default=datetime.datetime.now)
-    project = models.ForeignKey(Project)
-    spam = models.BooleanField(default=False)
-    
-    def get_absolute_url(self):
-        return self.project.get_absolute_url() + "#comment-" + str(self.id)
-    
-    def __unicode__(self):
-        return u'%s on %s' % (self.name, self.project.name)
-    
-    def snip(self):
-        return self.body[:40] + ('...' if len(self.body) > 40 else '')
-    
-
--- a/projects/urls.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-from django.conf.urls.defaults import *
-
-urlpatterns = patterns('projects.views',
-    url(r'^$',         'list',    name='project-list'),
-    url(r'^comment/$', 'comment', name='project-post-comment'),
-    url(r'^(.*)/$',    'project', name='project-view'),
-)
\ No newline at end of file
--- a/projects/views.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-from stevelosh.projects.models import Project, Comment
-from markdown import markdown
-from django.shortcuts import render_to_response, get_object_or_404
-from django.http import HttpResponseRedirect
-from django.core.urlresolvers import reverse
-from akismet import Akismet
-from stevelosh import deploy
-
-
-ak = Akismet(deploy.AKISMET_API_KEY, blog_url='http://stevelosh.com/')
-
-def project(request, slug):
-    project = get_object_or_404(Project, slug=slug)
-    comments = project.comment_set.filter(spam=False).order_by('submitted')
-    
-    return render_to_response('projects/project.html', 
-                              { 'project': project, 'comments': comments })
-
-def list(request):
-    photo = Project.objects.filter(type='photography').order_by('-posted')
-    programming = Project.objects.filter(type='programming').order_by('-posted')
-    return render_to_response('projects/list.html',
-        {'photo': photo, 'programming': programming})
-
-def comment(request):
-    fields = request.POST
-    project = Project.objects.get(pk=fields['project-id'])
-    
-    if ( fields.has_key('name') and 
-         not fields['name'].strip() == '' and
-         not len(fields['name']) < 2 and
-         fields.has_key('body') and 
-         not fields['body'].strip() == '' and
-         not len(fields['body']) < 3 and
-         not len(fields['body']) > 15000):
-        
-        akismet_data = {}
-        akismet_data['user_ip'] = request.META['REMOTE_ADDR']
-        akismet_data['user_agent'] = request.META['HTTP_USER_AGENT']
-        akismet_data['comment_author'] = fields['name']
-        akismet_data['comment_type'] ='comment'
-        spam = ak.comment_check(fields['body'].encode('ascii', 'ignore'), akismet_data)
-        
-        new_comment = Comment(name=fields['name'], 
-                              body=fields['body'], 
-                              project=project,
-                              spam=spam)
-        new_comment.save()
-    
-    return HttpResponseRedirect(reverse('project-view', args=(project.slug,)))
\ No newline at end of file
--- a/rss/feeds.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-from django.contrib.syndication.feeds import Feed
-from stevelosh.blog.models import Entry, Comment as BlogComment
-from stevelosh.projects.models import Project, Comment as ProjectComment
-import operator
-
-
-class LatestComments(Feed):
-    title = "Steve Losh / RSS / Comments"
-    link = "http://stevelosh.com/blog"
-    description = "Latest comments on blog entries from stevelosh.com"
-    
-    item_author_name = 'Steve Losh'
-    item_author_email = 'steve@stevelosh.com'
-    item_author_link = 'http://stevelosh.com'
-    
-    def items(self):
-        comments  = list(BlogComment.objects.filter(spam=False)
-                                            .order_by('-submitted')[:10])
-        comments += list(ProjectComment.objects.filter(spam=False)
-                                               .order_by('-submitted')[:10])
-        comments.sort(key=operator.attrgetter('submitted'))
-        comments.reverse()
-        return comments[:20]
-    
-    def item_pubdate(self, item):
-        return item.submitted
-    
-    def item_link(self, item):
-        return item.get_absolute_url()
-    
-
-class LatestEverything(Feed):
-    title = "Steve Losh"
-    link = "http://stevelosh.com"
-    description = "Latest updates from stevelosh.com"
-    
-    item_author_name = 'Steve Losh'
-    item_author_email = 'steve@stevelosh.com'
-    item_author_link = 'http://stevelosh.com'
-    
-    def items(self):
-        items = []
-        
-        items += [{'type': 'blog', 'item': entry, 'date': entry.pub_date, 'title': entry.title} 
-            for entry in Entry.objects.filter(published=True).order_by('-pub_date')[:10]]
-        
-        items += [{'type': 'project', 'item': project, 'date': project.posted, 'title': project.name}
-            for project in Project.objects.order_by('-posted')[:10]]
-        
-        items.sort(key=operator.itemgetter('date'))
-        items.reverse()
-        return items[:5]
-    
-    def item_pubdate(self, item):
-        return item['date']
-    
-    def item_link(self, item):
-        title = 'Steve Losh / ' + item['title']
-        new_link = item['item'].get_absolute_url()
-        
-        return new_link
-    
--- a/rss/urls.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-from django.conf.urls.defaults import *
-from stevelosh.rss.feeds import *
-
-feeds = { 'comments': LatestComments,
-          'all': LatestEverything, }
-
-urlpatterns = patterns('',
-    url(r'^(?P<url>.+)/$', 'django.contrib.syndication.views.feed', 
-        {'feed_dict': feeds}),
-)
\ No newline at end of file
--- a/settings.py	Sat Jan 09 03:42:18 2010 -0500
+++ b/settings.py	Sat Jan 09 04:01:49 2010 -0500
@@ -1,106 +1,87 @@
-from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS
 import os
-import deploy
+
+ROOT_PATH = os.path.abspath(os.path.dirname(__file__))
+
+import hydeengine
+HYDE_FOLDER = os.path.dirname(os.path.dirname(hydeengine.__file__))
+
+LAYOUT_DIR = os.path.join(ROOT_PATH, 'layout')
+CONTENT_DIR = os.path.join(ROOT_PATH, 'content')
+MEDIA_DIR = os.path.join(ROOT_PATH, 'media')
+DEPLOY_DIR = os.path.join(ROOT_PATH, 'deploy')
+TMP_DIR = os.path.join(ROOT_PATH, 'deploy_tmp')
+BACKUPS_DIR = os.path.join(ROOT_PATH, 'backups')
+
+BACKUP = False
+DEBUG = True
+
+SITE_ROOT = "/"
+SITE_WWW_URL = "http://stevelosh.com"
+SITE_NAME = "Steve Losh"
+SITE_AUTHOR = "Steve Losh"
+
+GENERATE_ABSOLUTE_FS_URLS = False
+GENERATE_CLEAN_URLS = True
+LISTING_PAGE_NAMES = ['index']
+APPEND_SLASH = True
+
+# {folder : extension : (processors)}
+# The processors are run in the given order and are chained.
+# Only a lone * is supported as an indicator for folders. Path 
+# should be specified. No wildcard card support yet.
+ 
+# Starting under the media folder. For example, if you have media/css under 
+# your site root,you should specify just css. If you have media/css/ie you 
+# should specify css/ie for the folder name. css/* is not supported (yet).
+
+# Extensions do not support wildcards.
+
+MEDIA_PROCESSORS = {
+    '*': {
+        '.css': ('hydeengine.media_processors.TemplateProcessor',
+                 'hydeengine.media_processors.YUICompressor',),
+        '.js': ('hydeengine.media_processors.TemplateProcessor',
+                'hydeengine.media_processors.YUICompressor',)
+    },
+    'images/': {
+        '.png': ('hydeengine.media_processors.Thumbnail',),
+        '.jpg': ('hydeengine.media_processors.Thumbnail',),
+    }
+}
+
+CONTENT_PROCESSORS = {}
+
+SITE_POST_PROCESSORS = {
+    # 'media/js': {
+    #        'hydeengine.site_post_processors.FolderFlattener' : {
+    #                'remove_processed_folders': True,
+    #                'pattern':"*.js"
+    #        }
+    #    }
+}
+
+CONTEXT = {
+    'GENERATE_CLEAN_URLS': GENERATE_CLEAN_URLS
+}
+
+FILTER = { 
+    'include': (".htaccess",),
+    'exclude': (".*","*~")
+}        
 
 
-DEBUG = deploy.DEBUG
-TEMPLATE_DEBUG = DEBUG
-
-ADMINS = (
-    ('Steve Losh', 'steve@stevelosh.com'),
-)
-
-MANAGERS = ADMINS
-
-DATABASE_ENGINE = deploy.DATABASE_ENGINE
-DATABASE_NAME = deploy.DATABASE_NAME
-DATABASE_USER = deploy.DATABASE_USER
-DATABASE_PASSWORD = deploy.DATABASE_PASSWORD
-DATABASE_HOST = deploy.DATABASE_HOST
-DATABASE_PORT = deploy.DATABASE_PORT
-
-# Local time zone for this installation. Choices can be found here:
-# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
-# although not all choices may be available on all operating systems.
-# If running in a Windows environment this must be set to the same as your
-# system time zone.
-TIME_ZONE = 'America/New_York'
+# Processor Configuration
 
-# Language code for this installation. All choices can be found here:
-# http://www.i18nguy.com/unicode/language-identifiers.html
-LANGUAGE_CODE = 'en-us'
-
-SITE_ID = 1
-
-# If you set this to False, Django will make some optimizations so as not
-# to load the internationalization machinery.
-USE_I18N = True
-
-# Base directory.
-BASE_DIR = os.path.dirname(__file__)
-
-# django-simplebackup settings
-BACKUP_DIRECTORY = os.path.join(BASE_DIR, 'backup')
-BACKUP_EXCLUDE = ['admin', 'sessions']
-
-# Absolute path to the directory that holds media.
-# Example: "/home/media/media.lawrence.com/"
-MEDIA_ROOT = os.path.join(BASE_DIR, 'site-media/')
-
-# URL that handles the media served from MEDIA_ROOT. Make sure to use a
-# trailing slash if there is a path component (optional in other cases).
-# Examples: "http://media.lawrence.com", "http://example.com/media/"
-MEDIA_URL = '/site-media/'
-
-LOGIN_URL = '/admin/'
+YUI_COMPRESSOR = os.path.join(HYDE_FOLDER, 'lib', 'yuicompressor-2.4.1.jar')
+HSS_PATH = None # if you don't want to use HSS
+THUMBNAIL_MAX_WIDTH = 140
+THUMBNAIL_MAX_HEIGHT = 300
+THUMBNAIL_FILENAME_POSTFIX = '-thumb'
 
-# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
-# trailing slash.
-# Examples: "http://foo.com/media/", "/media/".
-ADMIN_MEDIA_PREFIX = '/media/'
-MOBILEADMIN_MEDIA_PREFIX = '/media-mobile/'
-
-# Make this unique, and don't share it with anybody.
-SECRET_KEY = deploy.SECRET_KEY
-
-# List of callables that know how to import templates from various sources.
-TEMPLATE_LOADERS = (
-    'django.template.loaders.filesystem.load_template_source',
-    'django.template.loaders.app_directories.load_template_source',
-)
-
-MIDDLEWARE_CLASSES = (
-    'django.middleware.common.CommonMiddleware',
-    'django.contrib.sessions.middleware.SessionMiddleware',
-    'django.contrib.auth.middleware.AuthenticationMiddleware',
-    'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
-)
-
-ROOT_URLCONF = 'stevelosh.urls'
+# Django settings
 
-TEMPLATE_DIRS = (
-    os.path.join(BASE_DIR, 'templates/'),
-)
-
-TEMPLATE_CONTEXT_PROCESSORS += ( 
-    'mobileadmin.context_processors.user_agent', 
-)
-
+TEMPLATE_DIRS = (LAYOUT_DIR, CONTENT_DIR, TMP_DIR, MEDIA_DIR)
 INSTALLED_APPS = (
-    'django.contrib.auth',
-    'django.contrib.contenttypes',
-    'django.contrib.sessions',
-    'django.contrib.sites',
-    'django.contrib.admin',
-    'django.contrib.markup',
-    'django.contrib.flatpages',
-    'django.contrib.comments',
-    'stevelosh.blog',
-    'stevelosh.projects',
-    'stevelosh.messengerbag',
-    'mobileadmin',
-    'typogrify',
-    'disqus',
+    'hydeengine',
+    'django.contrib.webdesign',
 )
-
-from deploy import *
\ No newline at end of file
--- a/site-media/scripts/jquery.validate.min.js	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-/*
- * jQuery validation plug-in 1.5.3
- *
- * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
- * http://docs.jquery.com/Plugins/Validation
- *
- * Copyright (c) 2006 - 2008 Jörn Zaefferer
- *
- * $Id: jquery.validate.js 6390 2009-06-15 15:21:06Z joern.zaefferer $
- *
- * Dual licensed under the MIT and GPL licenses:
- *   http://www.opensource.org/licenses/mit-license.php
- *   http://www.gnu.org/licenses/gpl.html
- */
-(function($){$.extend($.fn,{validate:function(options){if(!this.length){options&&options.debug&&window.console&&console.warn("nothing selected, can't validate, returning nothing");return;}var validator=$.data(this[0],'validator');if(validator){return validator;}validator=new $.validator(options,this[0]);$.data(this[0],'validator',validator);if(validator.settings.onsubmit){this.find("input, button").filter(".cancel").click(function(){validator.cancelSubmit=true;});if(validator.settings.submitHandler){this.find("input, button").filter(":submit").click(function(){validator.submitButton=this;});}this.submit(function(event){if(validator.settings.debug)event.preventDefault();function handle(){if(validator.settings.submitHandler){if(validator.submitButton){var hidden=$("<input type='hidden'/>").attr("name",validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);}validator.settings.submitHandler.call(validator,validator.currentForm);if(validator.submitButton){hidden.remove();}return false;}return true;}if(validator.cancelSubmit){validator.cancelSubmit=false;return handle();}if(validator.form()){if(validator.pendingRequest){validator.formSubmitted=true;return false;}return handle();}else{validator.focusInvalid();return false;}});}return validator;},valid:function(){if($(this[0]).is('form')){return this.validate().form();}else{var valid=true;var validator=$(this[0].form).validate();this.each(function(){valid&=validator.element(this);});return valid;}},removeAttrs:function(attributes){var result={},$element=this;$.each(attributes.split(/\s/),function(index,value){result[value]=$element.attr(value);$element.removeAttr(value);});return result;},rules:function(command,argument){var element=this[0];if(command){var settings=$.data(element.form,'validator').settings;var staticRules=settings.rules;var existingRules=$.validator.staticRules(element);switch(command){case"add":$.extend(existingRules,$.validator.normalizeRule(argument));staticRules[element.name]=existingRules;if(argument.messages)settings.messages[element.name]=$.extend(settings.messages[element.name],argument.messages);break;case"remove":if(!argument){delete staticRules[element.name];return existingRules;}var filtered={};$.each(argument.split(/\s/),function(index,method){filtered[method]=existingRules[method];delete existingRules[method];});return filtered;}}var data=$.validator.normalizeRules($.extend({},$.validator.metadataRules(element),$.validator.classRules(element),$.validator.attributeRules(element),$.validator.staticRules(element)),element);if(data.required){var param=data.required;delete data.required;data=$.extend({required:param},data);}return data;}});$.extend($.expr[":"],{blank:function(a){return!$.trim(a.value);},filled:function(a){return!!$.trim(a.value);},unchecked:function(a){return!a.checked;}});$.validator=function(options,form){this.settings=$.extend({},$.validator.defaults,options);this.currentForm=form;this.init();};$.validator.format=function(source,params){if(arguments.length==1)return function(){var args=$.makeArray(arguments);args.unshift(source);return $.validator.format.apply(this,args);};if(arguments.length>2&&params.constructor!=Array){params=$.makeArray(arguments).slice(1);}if(params.constructor!=Array){params=[params];}$.each(params,function(i,n){source=source.replace(new RegExp("\\{"+i+"\\}","g"),n);});return source;};$.extend($.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:true,errorContainer:$([]),errorLabelContainer:$([]),onsubmit:true,ignore:[],ignoreTitle:false,onfocusin:function(element){this.lastActive=element;if(this.settings.focusCleanup&&!this.blockFocusCleanup){this.settings.unhighlight&&this.settings.unhighlight.call(this,element,this.settings.errorClass,this.settings.validClass);this.errorsFor(element).hide();}},onfocusout:function(element){if(!this.checkable(element)&&(element.name in this.submitted||!this.optional(element))){this.element(element);}},onkeyup:function(element){if(element.name in this.submitted||element==this.lastElement){this.element(element);}},onclick:function(element){if(element.name in this.submitted)this.element(element);},highlight:function(element,errorClass,validClass){$(element).addClass(errorClass).removeClass(validClass);},unhighlight:function(element,errorClass,validClass){$(element).removeClass(errorClass).addClass(validClass);}},setDefaults:function(settings){$.extend($.validator.defaults,settings);},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",dateDE:"Bitte geben Sie ein gültiges Datum ein.",number:"Please enter a valid number.",numberDE:"Bitte geben Sie eine Nummer ein.",digits:"Please enter only digits",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",accept:"Please enter a value with a valid extension.",maxlength:$.validator.format("Please enter no more than {0} characters."),minlength:$.validator.format("Please enter at least {0} characters."),rangelength:$.validator.format("Please enter a value between {0} and {1} characters long."),range:$.validator.format("Please enter a value between {0} and {1}."),max:$.validator.format("Please enter a value less than or equal to {0}."),min:$.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:false,prototype:{init:function(){this.labelContainer=$(this.settings.errorLabelContainer);this.errorContext=this.labelContainer.length&&this.labelContainer||$(this.currentForm);this.containers=$(this.settings.errorContainer).add(this.settings.errorLabelContainer);this.submitted={};this.valueCache={};this.pendingRequest=0;this.pending={};this.invalid={};this.reset();var groups=(this.groups={});$.each(this.settings.groups,function(key,value){$.each(value.split(/\s/),function(index,name){groups[name]=key;});});var rules=this.settings.rules;$.each(rules,function(key,value){rules[key]=$.validator.normalizeRule(value);});function delegate(event){var validator=$.data(this[0].form,"validator");validator.settings["on"+event.type]&&validator.settings["on"+event.type].call(validator,this[0]);}$(this.currentForm).delegate("focusin focusout keyup",":text, :password, :file, select, textarea",delegate).delegate("click",":radio, :checkbox",delegate);if(this.settings.invalidHandler)$(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler);},form:function(){this.checkForm();$.extend(this.submitted,this.errorMap);this.invalid=$.extend({},this.errorMap);if(!this.valid())$(this.currentForm).triggerHandler("invalid-form",[this]);this.showErrors();return this.valid();},checkForm:function(){this.prepareForm();for(var i=0,elements=(this.currentElements=this.elements());elements[i];i++){this.check(elements[i]);}return this.valid();},element:function(element){element=this.clean(element);this.lastElement=element;this.prepareElement(element);this.currentElements=$(element);var result=this.check(element);if(result){delete this.invalid[element.name];}else{this.invalid[element.name]=true;}if(!this.numberOfInvalids()){this.toHide=this.toHide.add(this.containers);}this.showErrors();return result;},showErrors:function(errors){if(errors){$.extend(this.errorMap,errors);this.errorList=[];for(var name in errors){this.errorList.push({message:errors[name],element:this.findByName(name)[0]});}this.successList=$.grep(this.successList,function(element){return!(element.name in errors);});}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors();},resetForm:function(){if($.fn.resetForm)$(this.currentForm).resetForm();this.submitted={};this.prepareForm();this.hideErrors();this.elements().removeClass(this.settings.errorClass);},numberOfInvalids:function(){return this.objectLength(this.invalid);},objectLength:function(obj){var count=0;for(var i in obj)count++;return count;},hideErrors:function(){this.addWrapper(this.toHide).hide();},valid:function(){return this.size()==0;},size:function(){return this.errorList.length;},focusInvalid:function(){if(this.settings.focusInvalid){try{$(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus();}catch(e){}}},findLastActive:function(){var lastActive=this.lastActive;return lastActive&&$.grep(this.errorList,function(n){return n.element.name==lastActive.name;}).length==1&&lastActive;},elements:function(){var validator=this,rulesCache={};return $([]).add(this.currentForm.elements).filter(":input").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){!this.name&&validator.settings.debug&&window.console&&console.error("%o has no name assigned",this);if(this.name in rulesCache||!validator.objectLength($(this).rules()))return false;rulesCache[this.name]=true;return true;});},clean:function(selector){return $(selector)[0];},errors:function(){return $(this.settings.errorElement+"."+this.settings.errorClass,this.errorContext);},reset:function(){this.successList=[];this.errorList=[];this.errorMap={};this.toShow=$([]);this.toHide=$([]);this.formSubmitted=false;this.currentElements=$([]);},prepareForm:function(){this.reset();this.toHide=this.errors().add(this.containers);},prepareElement:function(element){this.reset();this.toHide=this.errorsFor(element);},check:function(element){element=this.clean(element);if(this.checkable(element)){element=this.findByName(element.name)[0];}var rules=$(element).rules();var dependencyMismatch=false;for(method in rules){var rule={method:method,parameters:rules[method]};try{var result=$.validator.methods[method].call(this,element.value.replace(/\r/g,""),element,rule.parameters);if(result=="dependency-mismatch"){dependencyMismatch=true;continue;}dependencyMismatch=false;if(result=="pending"){this.toHide=this.toHide.not(this.errorsFor(element));return;}if(!result){this.formatAndAdd(element,rule);return false;}}catch(e){this.settings.debug&&window.console&&console.log("exception occured when checking element "+element.id
-+", check the '"+rule.method+"' method");throw e;}}if(dependencyMismatch)return;if(this.objectLength(rules))this.successList.push(element);return true;},customMetaMessage:function(element,method){if(!$.metadata)return;var meta=this.settings.meta?$(element).metadata()[this.settings.meta]:$(element).metadata();return meta&&meta.messages&&meta.messages[method];},customMessage:function(name,method){var m=this.settings.messages[name];return m&&(m.constructor==String?m:m[method]);},findDefined:function(){for(var i=0;i<arguments.length;i++){if(arguments[i]!==undefined)return arguments[i];}return undefined;},defaultMessage:function(element,method){return this.findDefined(this.customMessage(element.name,method),this.customMetaMessage(element,method),!this.settings.ignoreTitle&&element.title||undefined,$.validator.messages[method],"<strong>Warning: No message defined for "+element.name+"</strong>");},formatAndAdd:function(element,rule){var message=this.defaultMessage(element,rule.method);if(typeof message=="function")message=message.call(this,rule.parameters,element);this.errorList.push({message:message,element:element});this.errorMap[element.name]=message;this.submitted[element.name]=message;},addWrapper:function(toToggle){if(this.settings.wrapper)toToggle=toToggle.add(toToggle.parent(this.settings.wrapper));return toToggle;},defaultShowErrors:function(){for(var i=0;this.errorList[i];i++){var error=this.errorList[i];this.settings.highlight&&this.settings.highlight.call(this,error.element,this.settings.errorClass,this.settings.validClass);this.showLabel(error.element,error.message);}if(this.errorList.length){this.toShow=this.toShow.add(this.containers);}if(this.settings.success){for(var i=0;this.successList[i];i++){this.showLabel(this.successList[i]);}}if(this.settings.unhighlight){for(var i=0,elements=this.validElements();elements[i];i++){this.settings.unhighlight.call(this,elements[i],this.settings.errorClass,this.settings.validClass);}}this.toHide=this.toHide.not(this.toShow);this.hideErrors();this.addWrapper(this.toShow).show();},validElements:function(){return this.currentElements.not(this.invalidElements());},invalidElements:function(){return $(this.errorList).map(function(){return this.element;});},showLabel:function(element,message){var label=this.errorsFor(element);if(label.length){label.removeClass().addClass(this.settings.errorClass);label.attr("generated")&&label.html(message);}else{label=$("<"+this.settings.errorElement+"/>").attr({"for":this.idOrName(element),generated:true}).addClass(this.settings.errorClass).html(message||"");if(this.settings.wrapper){label=label.hide().show().wrap("<"+this.settings.wrapper+"/>").parent();}if(!this.labelContainer.append(label).length)this.settings.errorPlacement?this.settings.errorPlacement(label,$(element)):label.insertAfter(element);}if(!message&&this.settings.success){label.text("");typeof this.settings.success=="string"?label.addClass(this.settings.success):this.settings.success(label);}this.toShow=this.toShow.add(label);},errorsFor:function(element){return this.errors().filter("[for='"+this.idOrName(element)+"']");},idOrName:function(element){return this.groups[element.name]||(this.checkable(element)?element.name:element.id||element.name);},checkable:function(element){return/radio|checkbox/i.test(element.type);},findByName:function(name){var form=this.currentForm;return $(document.getElementsByName(name)).map(function(index,element){return element.form==form&&element.name==name&&element||null;});},getLength:function(value,element){switch(element.nodeName.toLowerCase()){case'select':return $("option:selected",element).length;case'input':if(this.checkable(element))return this.findByName(element.name).filter(':checked').length;}return value.length;},depend:function(param,element){return this.dependTypes[typeof param]?this.dependTypes[typeof param](param,element):true;},dependTypes:{"boolean":function(param,element){return param;},"string":function(param,element){return!!$(param,element.form).length;},"function":function(param,element){return param(element);}},optional:function(element){return!$.validator.methods.required.call(this,$.trim(element.value),element)&&"dependency-mismatch";},startRequest:function(element){if(!this.pending[element.name]){this.pendingRequest++;this.pending[element.name]=true;}},stopRequest:function(element,valid){this.pendingRequest--;if(this.pendingRequest<0)this.pendingRequest=0;delete this.pending[element.name];if(valid&&this.pendingRequest==0&&this.formSubmitted&&this.form()){$(this.currentForm).submit();}else if(!valid&&this.pendingRequest==0&&this.formSubmitted){$(this.currentForm).triggerHandler("invalid-form",[this]);}},previousValue:function(element){return $.data(element,"previousValue")||$.data(element,"previousValue",previous={old:null,valid:true,message:this.defaultMessage(element,"remote")});}},classRuleSettings:{required:{required:true},email:{email:true},url:{url:true},date:{date:true},dateISO:{dateISO:true},dateDE:{dateDE:true},number:{number:true},numberDE:{numberDE:true},digits:{digits:true},creditcard:{creditcard:true}},addClassRules:function(className,rules){className.constructor==String?this.classRuleSettings[className]=rules:$.extend(this.classRuleSettings,className);},classRules:function(element){var rules={};var classes=$(element).attr('class');classes&&$.each(classes.split(' '),function(){if(this in $.validator.classRuleSettings){$.extend(rules,$.validator.classRuleSettings[this]);}});return rules;},attributeRules:function(element){var rules={};var $element=$(element);for(method in $.validator.methods){var value=$element.attr(method);if(value){rules[method]=value;}}if(rules.maxlength&&/-1|2147483647|524288/.test(rules.maxlength)){delete rules.maxlength;}return rules;},metadataRules:function(element){if(!$.metadata)return{};var meta=$.data(element.form,'validator').settings.meta;return meta?$(element).metadata()[meta]:$(element).metadata();},staticRules:function(element){var rules={};var validator=$.data(element.form,'validator');if(validator.settings.rules){rules=$.validator.normalizeRule(validator.settings.rules[element.name])||{};}return rules;},normalizeRules:function(rules,element){$.each(rules,function(prop,val){if(val===false){delete rules[prop];return;}if(val.param||val.depends){var keepRule=true;switch(typeof val.depends){case"string":keepRule=!!$(val.depends,element.form).length;break;case"function":keepRule=val.depends.call(element,element);break;}if(keepRule){rules[prop]=val.param!==undefined?val.param:true;}else{delete rules[prop];}}});$.each(rules,function(rule,parameter){rules[rule]=$.isFunction(parameter)?parameter(element):parameter;});$.each(['minlength','maxlength','min','max'],function(){if(rules[this]){rules[this]=Number(rules[this]);}});$.each(['rangelength','range'],function(){if(rules[this]){rules[this]=[Number(rules[this][0]),Number(rules[this][1])];}});if($.validator.autoCreateRanges){if(rules.min&&rules.max){rules.range=[rules.min,rules.max];delete rules.min;delete rules.max;}if(rules.minlength&&rules.maxlength){rules.rangelength=[rules.minlength,rules.maxlength];delete rules.minlength;delete rules.maxlength;}}if(rules.messages){delete rules.messages}return rules;},normalizeRule:function(data){if(typeof data=="string"){var transformed={};$.each(data.split(/\s/),function(){transformed[this]=true;});data=transformed;}return data;},addMethod:function(name,method,message){$.validator.methods[name]=method;$.validator.messages[name]=message||$.validator.messages[name];if(method.length<3){$.validator.addClassRules(name,$.validator.normalizeRule(name));}},methods:{required:function(value,element,param){if(!this.depend(param,element))return"dependency-mismatch";switch(element.nodeName.toLowerCase()){case'select':var options=$("option:selected",element);return options.length>0&&(element.type=="select-multiple"||($.browser.msie&&!(options[0].attributes['value'].specified)?options[0].text:options[0].value).length>0);case'input':if(this.checkable(element))return this.getLength(value,element)>0;default:return $.trim(value).length>0;}},remote:function(value,element,param){if(this.optional(element))return"dependency-mismatch";var previous=this.previousValue(element);if(!this.settings.messages[element.name])this.settings.messages[element.name]={};this.settings.messages[element.name].remote=typeof previous.message=="function"?previous.message(value):previous.message;param=typeof param=="string"&&{url:param}||param;if(previous.old!==value){previous.old=value;var validator=this;this.startRequest(element);var data={};data[element.name]=value;$.ajax($.extend(true,{url:param,mode:"abort",port:"validate"+element.name,dataType:"json",data:data,success:function(response){if(response===true){var submitted=validator.formSubmitted;validator.prepareElement(element);validator.formSubmitted=submitted;validator.successList.push(element);validator.showErrors();}else{var errors={};errors[element.name]=response||validator.defaultMessage(element,"remote");validator.showErrors(errors);}previous.valid=response;validator.stopRequest(element,response);}},param));return"pending";}else if(this.pending[element.name]){return"pending";}return previous.valid;},minlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)>=param;},maxlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)<=param;},rangelength:function(value,element,param){var length=this.getLength($.trim(value),element);return this.optional(element)||(length>=param[0]&&length<=param[1]);},min:function(value,element,param){return this.optional(element)||value>=param;},max:function(value,element,param){return this.optional(element)||value<=param;},range:function(value,element,param){return this.optional(element)||(value>=param[0]&&value<=param[1]);},email:function(value,element){return this.optional(element)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);},url:function(value,element){return this.optional(element)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);},date:function(value,element){return this.optional(element)||!/Invalid|NaN/.test(new Date(value));},dateISO:function(value,element){return this.optional(element)||/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);},dateDE:function(value,element){return this.optional(element)||/^\d\d?\.\d\d?\.\d\d\d?\d?$/.test(value);},number:function(value,element){return this.optional(element)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);},numberDE:function(value,element){return this.optional(element)||/^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(value);},digits:function(value,element){return this.optional(element)||/^\d+$/.test(value);},creditcard:function(value,element){if(this.optional(element))return"dependency-mismatch";if(/[^0-9-]+/.test(value))return false;var nCheck=0,nDigit=0,bEven=false;value=value.replace(/\D/g,"");for(n=value.length-1;n>=0;n--){var cDigit=value.charAt(n);var nDigit=parseInt(cDigit,10);if(bEven){if((nDigit*=2)>9)nDigit-=9;}nCheck+=nDigit;bEven=!bEven;}return(nCheck%10)==0;},accept:function(value,element,param){param=typeof param=="string"?param.replace(/,/g,'|'):"png|jpe?g|gif";return this.optional(element)||value.match(new RegExp(".("+param+")$","i"));},equalTo:function(value,element,param){return value==$(param).val();}}});$.format=$.validator.format;})(jQuery);;(function($){var ajax=$.ajax;var pendingRequests={};$.ajax=function(settings){settings=$.extend(settings,$.extend({},$.ajaxSettings,settings));var port=settings.port;if(settings.mode=="abort"){if(pendingRequests[port]){pendingRequests[port].abort();}return(pendingRequests[port]=ajax.apply(this,arguments));}return ajax.apply(this,arguments);};})(jQuery);;(function($){$.each({focus:'focusin',blur:'focusout'},function(original,fix){$.event.special[fix]={setup:function(){if($.browser.msie)return false;this.addEventListener(original,$.event.special[fix].handler,true);},teardown:function(){if($.browser.msie)return false;this.removeEventListener(original,$.event.special[fix].handler,true);},handler:function(e){arguments[0]=$.event.fix(e);arguments[0].type=fix;return $.event.handle.apply(this,arguments);}};});$.extend($.fn,{delegate:function(type,delegate,handler){return this.bind(type,function(event){var target=$(event.target);if(target.is(delegate)){return handler.apply(target,arguments);}});},triggerEvent:function(type,target){return this.triggerHandler(type,[$.event.fix({type:type,target:target})]);}})})(jQuery);
\ No newline at end of file
--- a/site-media/scripts/print-links.js	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-$(document).ready(function() {
-    $('p:has(a)').add('ol:has(a)').add('ul:has(a)').each(function() {
-        var printing_links = $(this).find('a').clone();
-        $(this).after(printing_links);
-        
-        printing_links.wrap('<li></li>')
-                      .parent()
-                      .wrapAll('<ul class="print-links"></ul>');
-        
-        printing_links.each(function() {
-            $(this).after(': ' + $(this).attr('href'));
-        });
-    });
-});
\ No newline at end of file
--- a/site-media/scripts/stevelosh-gallery.js	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-$(function() {
-    $('div.gallery').each(function () {
-        $(this).contents().filter(function() {
-            return this.nodeType == Node.TEXT_NODE;
-        }).remove();
-        
-        var cols = 4;
-        var padding = 10;
-        var total_width = $(this).width();
-        var width = (total_width / cols) - 2 * padding;
-        $(this).find('img').css({width: width, margin: padding});
-        
-        $(this).before('<div class="gallery-pane"></div>');
-        $(this).find('img:first').clone()
-                                 .addClass('gallery-display')
-                                 .css({width: '', margin: ''})
-                                 .appendTo('div.gallery-pane');
-    });
-
-    $('div.gallery img').click(function() {
-        var new_image = $(this).clone()
-                               .addClass('gallery-display')
-                               .css({width: '', margin: '', display: 'none'});
-        $('img.gallery-display').fadeOut('fast', function() {
-            $(this).remove();
-            new_image.appendTo('div.gallery-pane').fadeIn('slow');
-        });
-    });
-});
\ No newline at end of file
--- a/site-media/scripts/validate-comment-form.js	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-$(document).ready(function() {
-	var validator = $("#new-comment-form").validate({
-		errorClass: 'invalid',
-		rules: {
-			name: {
-				required: true,
-				minlength: 2,
-				maxlength: 40
-			},
-			body: {
-				required: true,
-				minlength: 4,
-				maxlength: 15000
-			}
-		},
-		messages: {
-			name: {
-				required: "Please enter your name.",
-				minlength: jQuery.format("It has to be at least {0} letters."),
-				maxlength: jQuery.format("It can't be more than {0} letters."),
-			},
-			body: {
-				required: "Please enter a comment.",
-				minlength: jQuery.format("It has to be at least {0} letters."),
-				maxlength: jQuery.format("It can't be more than {0} letters."),
-			},
-		},
-		errorPlacement: function(error, element) {
-			error.appendTo( element.parent() );
-		},
-	});
-});
\ No newline at end of file
Binary file site-media/scripts/wmd/images/bg-fill.png has changed
Binary file site-media/scripts/wmd/images/bg.png has changed
Binary file site-media/scripts/wmd/images/blockquote.png has changed
Binary file site-media/scripts/wmd/images/bold.png has changed
Binary file site-media/scripts/wmd/images/code.png has changed
Binary file site-media/scripts/wmd/images/h1.png has changed
Binary file site-media/scripts/wmd/images/hr.png has changed
Binary file site-media/scripts/wmd/images/img.png has changed
Binary file site-media/scripts/wmd/images/italic.png has changed
Binary file site-media/scripts/wmd/images/link.png has changed
Binary file site-media/scripts/wmd/images/ol.png has changed
Binary file site-media/scripts/wmd/images/redo.png has changed
Binary file site-media/scripts/wmd/images/separator.png has changed
Binary file site-media/scripts/wmd/images/ul.png has changed
Binary file site-media/scripts/wmd/images/undo.png has changed
Binary file site-media/scripts/wmd/images/wmd-on.png has changed
Binary file site-media/scripts/wmd/images/wmd.png has changed
--- a/site-media/scripts/wmd/showdown.js	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,421 +0,0 @@
-var Attacklab=Attacklab||{};
-Attacklab.showdown=Attacklab.showdown||{};
-Attacklab.showdown.converter=function(){
-this.obfuscation;
-var _1;
-var _2;
-var _3;
-var _4=0;
-this.makeHtml=function(_5){
-_1=new Array();
-_2=new Array();
-_3=new Array();
-_5=_5.replace(/~/g,"~T");
-_5=_5.replace(/\$/g,"~D");
-_5=_5.replace(/\r\n/g,"\n");
-_5=_5.replace(/\r/g,"\n");
-_5="\n\n"+_5+"\n\n";
-_5=_6(_5);
-_5=_5.replace(/^[ \t]+$/mg,"");
-_5=_7(_5);
-_5=_8(_5);
-_5=_9(_5);
-_5=_a(_5);
-_5=_5.replace(/~D/g,"$$");
-_5=_5.replace(/~T/g,"~");
-return _5;
-};
-var _8=function(_b){
-var _b=_b.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm,function(_c,m1,m2,m3,m4){
-m1=m1.toLowerCase();
-_1[m1]=_11(m2);
-if(m3){
-return m3+m4;
-}else{
-if(m4){
-_2[m1]=m4.replace(/"/g,"&quot;");
-}
-}
-return "";
-});
-return _b;
-};
-var _7=function(_12){
-_12=_12.replace(/\n/g,"\n\n");
-var _13="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del";
-var _14="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math";
-_12=_12.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,_15);
-_12=_12.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm,_15);
-_12=_12.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,_15);
-_12=_12.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,_15);
-_12=_12.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,_15);
-_12=_12.replace(/\n\n/g,"\n");
-return _12;
-};
-var _15=function(_16,m1){
-var _18=m1;
-_18=_18.replace(/\n\n/g,"\n");
-_18=_18.replace(/^\n/,"");
-_18=_18.replace(/\n+$/g,"");
-_18="\n\n~K"+(_3.push(_18)-1)+"K\n\n";
-return _18;
-};
-var _9=function(_19){
-_19=_1a(_19);
-var key=_1c("<hr />");
-_19=_19.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,key);
-_19=_19.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,key);
-_19=_19.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,key);
-_19=_1d(_19);
-_19=_1e(_19);
-_19=_1f(_19);
-_19=_7(_19);
-_19=_20(_19);
-return _19;
-};
-var _21=function(_22){
-_22=_23(_22);
-_22=_24(_22);
-_22=_25(_22);
-_22=_26(_22);
-_22=_27(_22);
-_22=_28(_22);
-_22=_11(_22);
-_22=_29(_22);
-_22=_22.replace(/  +\n/g," <br />\n");
-return _22;
-};
-var _24=function(_2a){
-var _2b=/(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;
-_2a=_2a.replace(_2b,function(_2c){
-var tag=_2c.replace(/(.)<\/?code>(?=.)/g,"$1`");
-tag=_2e(tag,"\\`*_");
-return tag;
-});
-return _2a;
-};
-var _27=function(_2f){
-_2f=_2f.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,_30);
-_2f=_2f.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,_30);
-_2f=_2f.replace(/(\[([^\[\]]+)\])()()()()()/g,_30);
-return _2f;
-};
-var _30=function(_31,m1,m2,m3,m4,m5,m6,m7){
-if(m7==undefined){
-m7="";
-}
-var _39=m1;
-var _3a=m2;
-var _3b=m3.toLowerCase();
-var url=m4;
-var _3d=m7;
-if(url==""){
-if(_3b==""){
-_3b=_3a.toLowerCase().replace(/ ?\n/g," ");
-}
-url="#"+_3b;
-if(_1[_3b]!=undefined){
-url=_1[_3b];
-if(_2[_3b]!=undefined){
-_3d=_2[_3b];
-}
-}else{
-if(_39.search(/\(\s*\)$/m)>-1){
-url="";
-}else{
-return _39;
-}
-}
-}
-url=_2e(url,"*_");
-var _3e="<a href=\""+url+"\"";
-if(_3d!=""){
-_3d=_3d.replace(/"/g,"&quot;");
-_3d=_2e(_3d,"*_");
-_3e+=" title=\""+_3d+"\"";
-}
-_3e+=">"+_3a+"</a>";
-return _3e;
-};
-var _26=function(_3f){
-_3f=_3f.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,_40);
-_3f=_3f.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,_40);
-return _3f;
-};
-var _40=function(_41,m1,m2,m3,m4,m5,m6,m7){
-var _49=m1;
-var _4a=m2;
-var _4b=m3.toLowerCase();
-var url=m4;
-var _4d=m7;
-if(!_4d){
-_4d="";
-}
-if(url==""){
-if(_4b==""){
-_4b=_4a.toLowerCase().replace(/ ?\n/g," ");
-}
-url="#"+_4b;
-if(_1[_4b]!=undefined){
-url=_1[_4b];
-if(_2[_4b]!=undefined){
-_4d=_2[_4b];
-}
-}else{
-return _49;
-}
-}
-_4a=_4a.replace(/"/g,"&quot;");
-url=_2e(url,"*_");
-var _4e="<img src=\""+url+"\" alt=\""+_4a+"\"";
-_4d=_4d.replace(/"/g,"&quot;");
-_4d=_2e(_4d,"*_");
-_4e+=" title=\""+_4d+"\"";
-_4e+=" />";
-return _4e;
-};
-var _1a=function(_4f){
-_4f=_4f.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,function(_50,m1){
-return _1c("<h1>"+_21(m1)+"</h1>");
-});
-_4f=_4f.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,function(_52,m1){
-return _1c("<h2>"+_21(m1)+"</h2>");
-});
-_4f=_4f.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,function(_54,m1,m2){
-var _57=m1.length;
-return _1c("<h"+_57+">"+_21(m2)+"</h"+_57+">");
-});
-return _4f;
-};
-var _58;
-var _1d=function(_59){
-_59+="~0";
-var _5a=/^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
-if(_4){
-_59=_59.replace(_5a,function(_5b,m1,m2){
-var _5e=m1;
-var _5f=(m2.search(/[*+-]/g)>-1)?"ul":"ol";
-_5e=_5e.replace(/\n{2,}/g,"\n\n\n");
-var _60=_58(_5e);
-_60=_60.replace(/\s+$/,"");
-_60="<"+_5f+">"+_60+"</"+_5f+">\n";
-return _60;
-});
-}else{
-_5a=/(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;
-_59=_59.replace(_5a,function(_61,m1,m2,m3){
-var _65=m1;
-var _66=m2;
-var _67=(m3.search(/[*+-]/g)>-1)?"ul":"ol";
-var _66=_66.replace(/\n{2,}/g,"\n\n\n");
-var _68=_58(_66);
-_68=_65+"<"+_67+">\n"+_68+"</"+_67+">\n";
-return _68;
-});
-}
-_59=_59.replace(/~0/,"");
-return _59;
-};
-_58=function(_69){
-_4++;
-_69=_69.replace(/\n{2,}$/,"\n");
-_69+="~0";
-_69=_69.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,function(_6a,m1,m2,m3,m4){
-var _6f=m4;
-var _70=m1;
-var _71=m2;
-if(_70||(_6f.search(/\n{2,}/)>-1)){
-_6f=_9(_72(_6f));
-}else{
-_6f=_1d(_72(_6f));
-_6f=_6f.replace(/\n$/,"");
-_6f=_21(_6f);
-}
-return "<li>"+_6f+"</li>\n";
-});
-_69=_69.replace(/~0/g,"");
-_4--;
-return _69;
-};
-var _1e=function(_73){
-_73+="~0";
-_73=_73.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,function(_74,m1,m2){
-var _77=m1;
-var _78=m2;
-_77=_79(_72(_77));
-_77=_6(_77);
-_77=_77.replace(/^\n+/g,"");
-_77=_77.replace(/\n+$/g,"");
-_77="<pre><code>"+_77+"\n</code></pre>";
-return _1c(_77)+_78;
-});
-_73=_73.replace(/~0/,"");
-return _73;
-};
-var _1c=function(_7a){
-_7a=_7a.replace(/(^\n+|\n+$)/g,"");
-return "\n\n~K"+(_3.push(_7a)-1)+"K\n\n";
-};
-var _23=function(_7b){
-_7b=_7b.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(_7c,m1,m2,m3,m4){
-var c=m3;
-c=c.replace(/^([ \t]*)/g,"");
-c=c.replace(/[ \t]*$/g,"");
-c=_79(c);
-return m1+"<code>"+c+"</code>";
-});
-return _7b;
-};
-var _79=function(_82){
-_82=_82.replace(/&/g,"&amp;");
-_82=_82.replace(/</g,"&lt;");
-_82=_82.replace(/>/g,"&gt;");
-_82=_2e(_82,"*_{}[]\\",false);
-return _82;
-};
-var _29=function(_83){
-_83=_83.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,"<strong>$2</strong>");
-_83=_83.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,"<em>$2</em>");
-return _83;
-};
-this.hidetable;
-var _1f=function(_84){
-_84=_84.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,function(_85,m1){
-var bq=m1;
-bq=bq.replace(/^[ \t]*>[ \t]?/gm,"~0");
-bq=bq.replace(/~0/g,"");
-bq=bq.replace(/^[ \t]+$/gm,"");
-bq=_9(bq);
-bq=bq.replace(/(^|\n)/g,"$1  ");
-bq=bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm,function(_88,m1){
-var pre=m1;
-pre=pre.replace(/^  /mg,"~0");
-pre=pre.replace(/~0/g,"");
-return pre;
-});
-return _1c("<blockquote>\n"+bq+"\n</blockquote>");
-});
-return _84;
-};
-var _20=function(_8b){
-_8b=_8b.replace(/^\n+/g,"");
-_8b=_8b.replace(/\n+$/g,"");
-var _8c=_8b.split(/\n{2,}/g);
-var _8d=new Array();
-var end=_8c.length;
-for(var i=0;i<end;i++){
-var str=_8c[i];
-if(str.search(/~K(\d+)K/g)>=0){
-_8d.push(str);
-}else{
-if(str.search(/\S/)>=0){
-str=_21(str);
-str=str.replace(/^([ \t]*)/g,"<p>");
-str+="</p>";
-_8d.push(str);
-}
-}
-}
-end=_8d.length;
-for(var i=0;i<end;i++){
-while(_8d[i].search(/~K(\d+)K/)>=0){
-var _91=_3[RegExp.$1];
-_91=_91.replace(/\$/g,"$$$$");
-_8d[i]=_8d[i].replace(/~K\d+K/,_91);
-}
-}
-return _8d.join("\n\n");
-};
-var _11=function(_92){
-_92=_92.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&amp;");
-_92=_92.replace(/<(?![a-z\/?\$!])/gi,"&lt;");
-return _92;
-};
-var _25=function(_93){
-_93=_93.replace(/\\(\\)/g,_94);
-_93=_93.replace(/\\([`*_{}\[\]()>#+-.!])/g,_94);
-return _93;
-};
-var _28=function(_95){
-_95=_95.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"<a href=\"$1\">$1</a>");
-_95=_95.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,function(_96,m1){
-return _98(_a(m1));
-});
-return _95;
-};
-var _98=function(_99){
-function char2hex(ch){
-var _9b="0123456789ABCDEF";
-var dec=ch.charCodeAt(0);
-return (_9b.charAt(dec>>4)+_9b.charAt(dec&15));
-}
-var _9d=[function(ch){
-return "&#"+ch.charCodeAt(0)+";";
-},function(ch){
-return "&#x"+char2hex(ch)+";";
-},function(ch){
-return ch;
-}];
-_99="mailto:"+_99;
-_99=_99.replace(/./g,function(ch){
-if(ch=="@"){
-ch=_9d[Math.floor(Math.random()*2)](ch);
-}else{
-if(ch!=":"){
-var r=Math.random();
-ch=(r>0.9?_9d[2](ch):r>0.45?_9d[1](ch):_9d[0](ch));
-}
-}
-return ch;
-});
-_99="<a href=\""+_99+"\">"+_99+"</a>";
-_99=_99.replace(/">.+:/g,"\">");
-return _99;
-};
-var _a=function(_a3){
-_a3=_a3.replace(/~E(\d+)E/g,function(_a4,m1){
-var _a6=parseInt(m1);
-return String.fromCharCode(_a6);
-});
-return _a3;
-};
-var _72=function(_a7){
-_a7=_a7.replace(/^(\t|[ ]{1,4})/gm,"~0");
-_a7=_a7.replace(/~0/g,"");
-return _a7;
-};
-var _6=function(_a8){
-_a8=_a8.replace(/\t(?=\t)/g,"    ");
-_a8=_a8.replace(/\t/g,"~A~B");
-_a8=_a8.replace(/~B(.+?)~A/g,function(_a9,m1,m2){
-var _ac=m1;
-var _ad=4-_ac.length%4;
-for(var i=0;i<_ad;i++){
-_ac+=" ";
-}
-return _ac;
-});
-_a8=_a8.replace(/~A/g,"    ");
-_a8=_a8.replace(/~B/g,"");
-return _a8;
-};
-var _2e=function(_af,_b0,_b1){
-var _b2="(["+_b0.replace(/([\[\]\\])/g,"\\$1")+"])";
-if(_b1){
-_b2="\\\\"+_b2;
-}
-var _b3=new RegExp(_b2,"g");
-_af=_af.replace(_b3,_94);
-return _af;
-};
-var _94=function(_b4,m1){
-var _b6=m1.charCodeAt(0);
-return "~E"+_b6+"E";
-};
-this.obfuscation;
-};
-var Showdown=Attacklab.showdown;
-if(Attacklab.fileLoaded){
-Attacklab.fileLoaded("showdown.js");
-}
-
--- a/site-media/scripts/wmd/wmd-base.js	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1799 +0,0 @@
-var Attacklab=Attacklab||{};
-Attacklab.wmdBase=function(){
-var _1=top;
-var _2=_1["Attacklab"];
-var _3=_1["document"];
-var _4=_1["RegExp"];
-var _5=_1["navigator"];
-_2.Util={};
-_2.Position={};
-_2.Command={};
-var _6=_2.Util;
-var _7=_2.Position;
-var _8=_2.Command;
-_2.Util.IE=(_5.userAgent.indexOf("MSIE")!=-1);
-_2.Util.oldIE=(_5.userAgent.indexOf("MSIE 6.")!=-1||_5.userAgent.indexOf("MSIE 5.")!=-1);
-_2.Util.newIE=!_2.Util.oldIE&&(_5.userAgent.indexOf("MSIE")!=-1);
-_6.makeElement=function(_9,_a){
-var _b=_3.createElement(_9);
-if(!_a){
-var _c=_b.style;
-_c.margin="0";
-_c.padding="0";
-_c.clear="none";
-_c.cssFloat="none";
-_c.textAlign="left";
-_c.position="relative";
-_c.lineHeight="1em";
-_c.border="none";
-_c.color="black";
-_c.backgroundRepeat="no-repeat";
-_c.backgroundImage="none";
-_c.minWidth=_c.minHeight="0";
-_c.maxWidth=_c.maxHeight="90000px";
-}
-return _b;
-};
-_6.getStyle=function(_d,_e){
-var _f=function(_10){
-return _10.replace(/-(\S)/g,function(_11,_12){
-return _12.toUpperCase();
-});
-};
-if(_d.currentStyle){
-_e=_f(_e);
-return _d.currentStyle[_e];
-}else{
-if(_1.getComputedStyle){
-return _3.defaultView.getComputedStyle(_d,null).getPropertyValue(_e);
-}
-}
-return "";
-};
-_6.getElementsByClass=function(_13,_14,_15){
-var _16=[];
-if(_14==null){
-_14=_3;
-}
-if(_15==null){
-_15="*";
-}
-var _17=_14.getElementsByTagName(_15);
-var _18=_17.length;
-var _19=new _4("(^|\\s)"+_13+"(\\s|$)");
-for(var i=0,j=0;i<_18;i++){
-if(_19.test(_17[i].className.toLowerCase())){
-_16[j]=_17[i];
-j++;
-}
-}
-return _16;
-};
-_6.addEvent=function(_1c,_1d,_1e){
-if(_1c.attachEvent){
-_1c.attachEvent("on"+_1d,_1e);
-}else{
-_1c.addEventListener(_1d,_1e,false);
-}
-};
-_6.removeEvent=function(_1f,_20,_21){
-if(_1f.detachEvent){
-_1f.detachEvent("on"+_20,_21);
-}else{
-_1f.removeEventListener(_20,_21,false);
-}
-};
-_6.regexToString=function(_22){
-var _23={};
-var _24=_22.toString();
-_23.expression=_24.replace(/\/([gim]*)$/,"");
-_23.flags=_4.$1;
-_23.expression=_23.expression.replace(/(^\/|\/$)/g,"");
-return _23;
-};
-_6.stringToRegex=function(_25){
-return new _4(_25.expression,_25.flags);
-};
-_6.elementOk=function(_26){
-if(!_26||!_26.parentNode){
-return false;
-}
-if(_6.getStyle(_26,"display")=="none"){
-return false;
-}
-return true;
-};
-_6.skin=function(_27,_28,_29,_2a){
-var _2b;
-var _2c=(_5.userAgent.indexOf("MSIE")!=-1);
-if(_2c){
-_6.fillers=[];
-}
-var _2d=_29/2;
-for(var _2e=0;_2e<4;_2e++){
-var _2f=_6.makeElement("div");
-_2b=_2f.style;
-_2b.overflow="hidden";
-_2b.padding="0";
-_2b.margin="0";
-_2b.lineHeight="0px";
-_2b.height=_2d+"px";
-_2b.width="50%";
-_2b.maxHeight=_2d+"px";
-_2b.position="absolute";
-if(_2e&1){
-_2b.top="0";
-}else{
-_2b.bottom=-_29+"px";
-}
-_2b.zIndex="-1000";
-if(_2e&2){
-_2b.left="0";
-}else{
-_2b.marginLeft="50%";
-}
-if(_2c){
-var _30=_6.makeElement("span");
-_2b=_30.style;
-_2b.height="100%";
-_2b.width=_2a;
-_2b.filter="progid:DXImageTransform.Microsoft."+"AlphaImageLoader(src='"+_2.basePath+"images/bg.png')";
-_2b.position="absolute";
-if(_2e&1){
-_2b.top="0";
-}else{
-_2b.bottom="0";
-}
-if(_2e&2){
-_2b.left="0";
-}else{
-_2b.right="0";
-}
-_2f.appendChild(_30);
-}else{
-_2b.backgroundImage="url("+_28+")";
-_2b.backgroundPosition=(_2e&2?"left":"right")+" "+(_2e&1?"top":"bottom");
-}
-_27.appendChild(_2f);
-}
-var _31=function(_32){
-var _33=_6.makeElement("div");
-if(_6.fillers){
-_6.fillers.push(_33);
-}
-_2b=_33.style;
-_2b.overflow="hidden";
-_2b.padding="0";
-_2b.margin="0";
-_2b.marginTop=_2d+"px";
-_2b.lineHeight="0px";
-_2b.height="100%";
-_2b.width="50%";
-_2b.position="absolute";
-_2b.zIndex="-1000";
-if(_2c){
-var _34=_6.makeElement("span");
-_2b=_34.style;
-_2b.height="100%";
-_2b.width=_2a;
-_2b.filter="progid:DXImageTransform.Microsoft."+"AlphaImageLoader(src='"+_2.basePath+"images/bg-fill.png',sizingMethod='scale')";
-_2b.position="absolute";
-_33.appendChild(_34);
-if(_32){
-_2b.left="0";
-}
-if(!_32){
-_2b.right="0";
-}
-}
-if(!_2c){
-_2b.backgroundImage="url("+_2.basePath+"images/bg-fill.png)";
-_2b.backgroundRepeat="repeat-y";
-if(_32){
-_2b.backgroundPosition="left top";
-}
-if(!_32){
-_2b.backgroundPosition="right top";
-}
-}
-if(!_32){
-_33.style.marginLeft="50%";
-}
-return _33;
-};
-_27.appendChild(_31(true));
-_27.appendChild(_31(false));
-};
-_6.setImage=function(_35,_36,_37,_38){
-_36=_2.basePath+_36;
-if(_5.userAgent.indexOf("MSIE")!=-1){
-var _39=_35.firstChild;
-var _3a=_39.style;
-_3a.filter="progid:DXImageTransform.Microsoft."+"AlphaImageLoader(src='"+_36+"')";
-}else{
-_35.src=_36;
-}
-return _35;
-};
-_6.createImage=function(_3b,_3c,_3d){
-_3b=_2.basePath+_3b;
-if(_5.userAgent.indexOf("MSIE")!=-1){
-var _3e=_6.makeElement("span");
-var _3f=_3e.style;
-_3f.display="inline-block";
-_3f.height="1px";
-_3f.width="1px";
-_3e.unselectable="on";
-var _40=_6.makeElement("span");
-_3f=_40.style;
-_3f.display="inline-block";
-_3f.height="1px";
-_3f.width="1px";
-_3f.filter="progid:DXImageTransform.Microsoft."+"AlphaImageLoader(src='"+_3b+"')";
-_40.unselectable="on";
-_3e.appendChild(_40);
-}else{
-var _3e=_6.makeElement("img");
-_3e.style.display="inline";
-_3e.src=_3b;
-}
-_3e.style.border="none";
-_3e.border="0";
-if(_3c&&_3d){
-_3e.style.width=_3c+"px";
-_3e.style.height=_3d+"px";
-}
-return _3e;
-};
-_6.prompt=function(_41,_42,_43){
-var _44;
-var _45,_46,_47;
-var _48=function(_49){
-var _4a=(_49.charCode||_49.keyCode);
-if(_4a==27){
-_4b(true);
-}
-};
-var _4b=function(_4c){
-_6.removeEvent(_3.body,"keydown",_48);
-var _4d=_47.value;
-if(_4c){
-_4d=null;
-}
-_45.parentNode.removeChild(_45);
-_46.parentNode.removeChild(_46);
-_43(_4d);
-return false;
-};
-if(_42==undefined){
-_42="";
-}
-var _4e=function(){
-_46=_6.makeElement("div");
-_44=_46.style;
-_3.body.appendChild(_46);
-_44.position="absolute";
-_44.top="0";
-_44.left="0";
-_44.backgroundColor="#000";
-_44.zIndex="1000";
-var _4f=/konqueror/.test(_5.userAgent.toLowerCase());
-if(_4f){
-_44.backgroundColor="transparent";
-}else{
-_44.opacity="0.5";
-_44.filter="alpha(opacity=50)";
-}
-var _50=_7.getPageSize();
-_44.width="100%";
-_44.height=_50[1]+"px";
-};
-var _51=function(){
-_45=_3.createElement("div");
-_45.style.border="3px solid #333";
-_45.style.backgroundColor="#ccc";
-_45.style.padding="10px;";
-_45.style.borderTop="3px solid white";
-_45.style.borderLeft="3px solid white";
-_45.style.position="fixed";
-_45.style.width="400px";
-_45.style.zIndex="1001";
-var _52=_6.makeElement("div");
-_44=_52.style;
-_44.fontSize="14px";
-_44.fontFamily="Helvetica, Arial, Verdana, sans-serif";
-_44.padding="5px";
-_52.innerHTML=_41;
-_45.appendChild(_52);
-var _53=_6.makeElement("form");
-_53.onsubmit=function(){
-return _4b();
-};
-_44=_53.style;
-_44.padding="0";
-_44.margin="0";
-_44.cssFloat="left";
-_44.width="100%";
-_44.textAlign="center";
-_44.position="relative";
-_45.appendChild(_53);
-_47=_3.createElement("input");
-_47.value=_42;
-_44=_47.style;
-_44.display="block";
-_44.width="80%";
-_44.marginLeft=_44.marginRight="auto";
-_44.backgroundColor="white";
-_44.color="black";
-_53.appendChild(_47);
-var _54=_3.createElement("input");
-_54.type="button";
-_54.onclick=function(){
-return _4b();
-};
-_54.value="OK";
-_44=_54.style;
-_44.margin="10px";
-_44.display="inline";
-_44.width="7em";
-var _55=_3.createElement("input");
-_55.type="button";
-_55.onclick=function(){
-return _4b(true);
-};
-_55.value="Cancel";
-_44=_55.style;
-_44.margin="10px";
-_44.display="inline";
-_44.width="7em";
-if(/mac/.test(_5.platform.toLowerCase())){
-_53.appendChild(_55);
-_53.appendChild(_54);
-}else{
-_53.appendChild(_54);
-_53.appendChild(_55);
-}
-_6.addEvent(_3.body,"keydown",_48);
-_45.style.top="50%";
-_45.style.left="50%";
-_45.style.display="block";
-if(_2.Util.oldIE){
-var _56=_7.getPageSize();
-_45.style.position="absolute";
-_45.style.top=_3.documentElement.scrollTop+200+"px";
-_45.style.left="50%";
-}
-_3.body.appendChild(_45);
-_45.style.marginTop=-(_7.getHeight(_45)/2)+"px";
-_45.style.marginLeft=-(_7.getWidth(_45)/2)+"px";
-};
-_4e();
-_1.setTimeout(function(){
-_51();
-var _57=_42.length;
-if(_47.selectionStart!=undefined){
-_47.selectionStart=0;
-_47.selectionEnd=_57;
-}else{
-if(_47.createTextRange){
-var _58=_47.createTextRange();
-_58.collapse(false);
-_58.moveStart("character",-_57);
-_58.moveEnd("character",_57);
-_58.select();
-}
-}
-_47.focus();
-},0);
-};
-_6.objectsEqual=function(_59,_5a){
-for(var _5b in _59){
-if(_59[_5b]!=_5a[_5b]){
-return false;
-}
-}
-for(_5b in _5a){
-if(_59[_5b]!=_5a[_5b]){
-return false;
-}
-}
-return true;
-};
-_6.cloneObject=function(_5c){
-var _5d={};
-for(var _5e in _5c){
-_5d[_5e]=_5c[_5e];
-}
-return _5d;
-};
-_6.escapeUnderscores=function(_5f){
-_5f=_5f.replace(/(\S)(_+)(\S)/g,function(_60,_61,_62,_63){
-_62=_62.replace(/_/g,"&#95;");
-return _61+_62+_63;
-});
-return _5f;
-};
-_7.getPageSize=function(){
-var _64,_65;
-var _66,_67;
-if(_1.innerHeight&&_1.scrollMaxY){
-_64=_3.body.scrollWidth;
-_65=_1.innerHeight+_1.scrollMaxY;
-}else{
-if(_3.body.scrollHeight>_3.body.offsetHeight){
-_64=_3.body.scrollWidth;
-_65=_3.body.scrollHeight;
-}else{
-_64=_3.body.offsetWidth;
-_65=_3.body.offsetHeight;
-}
-}
-var _68,_69;
-if(self.innerHeight){
-_68=self.innerWidth;
-_69=self.innerHeight;
-}else{
-if(_3.documentElement&&_3.documentElement.clientHeight){
-_68=_3.documentElement.clientWidth;
-_69=_3.documentElement.clientHeight;
-}else{
-if(_3.body){
-_68=_3.body.clientWidth;
-_69=_3.body.clientHeight;
-}
-}
-}
-if(_65<_69){
-_67=_69;
-}else{
-_67=_65;
-}
-if(_64<_68){
-_66=_68;
-}else{
-_66=_64;
-}
-var _6a=[_66,_67,_68,_69];
-return _6a;
-};
-_7.getPixelVal=function(_6b){
-if(_6b&&/^(-?\d+(\.\d*)?)px$/.test(_6b)){
-return _4.$1;
-}
-return undefined;
-};
-_7.getTop=function(_6c,_6d){
-var _6e=_6c.offsetTop;
-if(!_6d){
-while(_6c=_6c.offsetParent){
-_6e+=_6c.offsetTop;
-}
-}
-return _6e;
-};
-_7.setTop=function(_6f,_70,_71){
-var _72=_7.getPixelVal(_6f.style.top);
-if(_72==undefined){
-_6f.style.top=_70+"px";
-_72=_70;
-}
-var _73=_7.getTop(_6f,_71)-_72;
-_6f.style.top=(_70-_73)+"px";
-};
-_7.getLeft=function(_74,_75){
-var _76=_74.offsetLeft;
-if(!_75){
-while(_74=_74.offsetParent){
-_76+=_74.offsetLeft;
-}
-}
-return _76;
-};
-_7.setLeft=function(_77,_78,_79){
-var _7a=_7.getPixelVal(_77.style.left);
-if(_7a==undefined){
-_77.style.left=_78+"px";
-_7a=_78;
-}
-var _7b=_7.getLeft(_77,_79)-_7a;
-_77.style.left=(_78-_7b)+"px";
-};
-_7.getHeight=function(_7c){
-var _7d=_7c.offsetHeight;
-if(!_7d){
-_7d=_7c.scrollHeight;
-}
-return _7d;
-};
-_7.setHeight=function(_7e,_7f){
-var _80=_7.getPixelVal(_7e.style.height);
-if(_80==undefined){
-_7e.style.height=_7f+"px";
-_80=_7f;
-}
-var _81=_7.getHeight(_7e)-_80;
-if(_81>_7f){
-_81=_7f;
-}
-_7e.style.height=(_7f-_81)+"px";
-};
-_7.getWidth=function(_82){
-var _83=_82.offsetWidth;
-if(!_83){
-_83=_82.scrollWidth;
-}
-return _83;
-};
-_7.setWidth=function(_84,_85){
-var _86=_7.getPixelVal(_84.style.width);
-if(_86==undefined){
-_84.style.width=_85+"px";
-_86=_85;
-}
-var _87=_7.getWidth(_84)-_86;
-if(_87>_85){
-_87=_85;
-}
-_84.style.width=(_85-_87)+"px";
-};
-_7.getWindowHeight=function(){
-if(_1.innerHeight){
-return _1.innerHeight;
-}else{
-if(_3.documentElement&&_3.documentElement.clientHeight){
-return _3.documentElement.clientHeight;
-}else{
-if(_3.body){
-return _3.body.clientHeight;
-}
-}
-}
-};
-_2.inputPoller=function(_88,_89,_8a){
-var _8b=this;
-var _8c;
-var _8d;
-var _8e,_8f;
-this.tick=function(){
-if(!_6.elementOk(_88)){
-return;
-}
-if(_88.selectionStart||_88.selectionStart==0){
-var _90=_88.selectionStart;
-var _91=_88.selectionEnd;
-if(_90!=_8c||_91!=_8d){
-_8c=_90;
-_8d=_91;
-if(_8e!=_88.value){
-_8e=_88.value;
-return true;
-}
-}
-}
-return false;
-};
-var _92=function(){
-if(_6.getStyle(_88,"display")=="none"){
-return;
-}
-if(_8b.tick()){
-_89();
-}
-};
-var _93=function(){
-if(_8a==undefined){
-_8a=500;
-}
-_8f=_1.setInterval(_92,_8a);
-};
-this.destroy=function(){
-_1.clearInterval(_8f);
-};
-_93();
-};
-_2.undoManager=function(_94,_95){
-var _96=this;
-var _97=[];
-var _98=0;
-var _99="none";
-var _9a;
-var _9b;
-var _9c;
-var _9d;
-var _9e=function(_9f,_a0){
-if(_99!=_9f){
-_99=_9f;
-if(!_a0){
-_a1();
-}
-}
-if(!_2.Util.IE||_99!="moving"){
-_9c=_1.setTimeout(_a2,1);
-}else{
-_9d=null;
-}
-};
-var _a2=function(){
-_9d=new _2.textareaState(_94);
-_9b.tick();
-_9c=undefined;
-};
-this.setCommandMode=function(){
-_99="command";
-_a1();
-_9c=_1.setTimeout(_a2,0);
-};
-this.canUndo=function(){
-return _98>1;
-};
-this.canRedo=function(){
-if(_97[_98+1]){
-return true;
-}
-return false;
-};
-this.undo=function(){
-if(_96.canUndo()){
-if(_9a){
-_9a.restore();
-_9a=null;
-}else{
-_97[_98]=new _2.textareaState(_94);
-_97[--_98].restore();
-if(_95){
-_95();
-}
-}
-}
-_99="none";
-_94.focus();
-_a2();
-};
-this.redo=function(){
-if(_96.canRedo()){
-_97[++_98].restore();
-if(_95){
-_95();
-}
-}
-_99="none";
-_94.focus();
-_a2();
-};
-var _a1=function(){
-var _a3=_9d||new _2.textareaState(_94);
-if(!_a3){
-return false;
-}
-if(_99=="moving"){
-if(!_9a){
-_9a=_a3;
-}
-return;
-}
-if(_9a){
-if(_97[_98-1].text!=_9a.text){
-_97[_98++]=_9a;
-}
-_9a=null;
-}
-_97[_98++]=_a3;
-_97[_98+1]=null;
-if(_95){
-_95();
-}
-};
-var _a4=function(_a5){
-var _a6=false;
-if(_a5.ctrlKey||_a5.metaKey){
-var _a7=(_a5.charCode||_a5.keyCode)|96;
-var _a8=String.fromCharCode(_a7);
-switch(_a8){
-case "y":
-_96.redo();
-_a6=true;
-break;
-case "z":
-if(!_a5.shiftKey){
-_96.undo();
-}else{
-_96.redo();
-}
-_a6=true;
-break;
-}
-}
-if(_a6){
-if(_a5.preventDefault){
-_a5.preventDefault();
-}
-if(_1.event){
-_1.event.returnValue=false;
-}
-return;
-}
-};
-var _a9=function(_aa){
-if(!_aa.ctrlKey&&!_aa.metaKey){
-var _ab=_aa.keyCode;
-if((_ab>=33&&_ab<=40)||(_ab>=63232&&_ab<=63235)){
-_9e("moving");
-}else{
-if(_ab==8||_ab==46||_ab==127){
-_9e("deleting");
-}else{
-if(_ab==13){
-_9e("newlines");
-}else{
-if(_ab==27){
-_9e("escape");
-}else{
-if((_ab<16||_ab>20)&&_ab!=91){
-_9e("typing");
-}
-}
-}
-}
-}
-}
-};
-var _ac=function(){
-_6.addEvent(_94,"keypress",function(_ad){
-if((_ad.ctrlKey||_ad.metaKey)&&(_ad.keyCode==89||_ad.keyCode==90)){
-_ad.preventDefault();
-}
-});
-var _ae=function(){
-if(_2.Util.IE||(_9d&&_9d.text!=_94.value)){
-if(_9c==undefined){
-_99="paste";
-_a1();
-_a2();
-}
-}
-};
-_9b=new _2.inputPoller(_94,_ae,100);
-_6.addEvent(_94,"keydown",_a4);
-_6.addEvent(_94,"keydown",_a9);
-_6.addEvent(_94,"mousedown",function(){
-_9e("moving");
-});
-_94.onpaste=_ae;
-_94.ondrop=_ae;
-};
-var _af=function(){
-_ac();
-_a2();
-_a1();
-};
-this.destroy=function(){
-if(_9b){
-_9b.destroy();
-}
-};
-_af();
-};
-_2.editor=function(_b0,_b1){
-if(!_b1){
-_b1=function(){
-};
-}
-var _b2=28;
-var _b3=4076;
-var _b4=0;
-var _b5,_b6;
-var _b7=this;
-var _b8,_b9;
-var _ba,_bb,_bc;
-var _bd,_be,_bf;
-var _c0=[];
-var _c1=function(_c2){
-if(_bd){
-_bd.setCommandMode();
-}
-var _c3=new _2.textareaState(_b0);
-if(!_c3){
-return;
-}
-var _c4=_c3.getChunks();
-var _c5=function(){
-_b0.focus();
-if(_c4){
-_c3.setChunks(_c4);
-}
-_c3.restore();
-_b1();
-};
-var _c6=_c2(_c4,_c5);
-if(!_c6){
-_c5();
-}
-};
-var _c7=function(_c8){
-_b0.focus();
-if(_c8.textOp){
-_c1(_c8.textOp);
-}
-if(_c8.execute){
-_c8.execute(_b7);
-}
-};
-var _c9=function(_ca,_cb){
-var _cc=_ca.style;
-if(_cb){
-_cc.opacity="1.0";
-_cc.KHTMLOpacity="1.0";
-if(_2.Util.newIE){
-_cc.filter="";
-}
-if(_2.Util.oldIE){
-_cc.filter="chroma(color=fuchsia)";
-}
-_cc.cursor="pointer";
-_ca.onmouseover=function(){
-_cc.backgroundColor="lightblue";
-_cc.border="1px solid blue";
-};
-_ca.onmouseout=function(){
-_cc.backgroundColor="";
-_cc.border="1px solid transparent";
-if(_2.Util.oldIE){
-_cc.borderColor="fuchsia";
-_cc.filter="chroma(color=fuchsia)"+_cc.filter;
-}
-};
-}else{
-_cc.opacity="0.4";
-_cc.KHTMLOpacity="0.4";
-if(_2.Util.oldIE){
-_cc.filter="chroma(color=fuchsia) alpha(opacity=40)";
-}
-if(_2.Util.newIE){
-_cc.filter="alpha(opacity=40)";
-}
-_cc.cursor="";
-_cc.backgroundColor="";
-if(_ca.onmouseout){
-_ca.onmouseout();
-}
-_ca.onmouseover=_ca.onmouseout=null;
-}
-};
-var _cd=function(_ce){
-_ce&&_c0.push(_ce);
-};
-var _cf=function(){
-_c0.push("|");
-};
-var _d0=function(){
-var _d1=_6.createImage("images/separator.png",20,20);
-_d1.style.padding="4px";
-_d1.style.paddingTop="0px";
-_b9.appendChild(_d1);
-};
-var _d2=function(_d3){
-if(_d3.image){
-var _d4=_6.createImage(_d3.image,16,16);
-_d4.border=0;
-if(_d3.description){
-var _d5=_d3.description;
-if(_d3.key){
-var _d6=" Ctrl+";
-_d5+=_d6+_d3.key.toUpperCase();
-}
-_d4.title=_d5;
-}
-_c9(_d4,true);
-var _d7=_d4.style;
-_d7.margin="0px";
-_d7.padding="1px";
-_d7.marginTop="7px";
-_d7.marginBottom="5px";
-_d4.onmouseout();
-var _d8=_d4;
-_d8.onclick=function(){
-if(_d8.onmouseout){
-_d8.onmouseout();
-}
-_c7(_d3);
-return false;
-};
-_b9.appendChild(_d8);
-return _d8;
-}
-return;
-};
-var _d9=function(){
-for(var _da in _c0){
-if(_c0[_da]=="|"){
-_d0();
-}else{
-_d2(_c0[_da]);
-}
-}
-};
-var _db=function(){
-if(_bd){
-_c9(_be,_bd.canUndo());
-_c9(_bf,_bd.canRedo());
-}
-};
-var _dc=function(){
-if(_b0.offsetParent){
-_ba=_6.makeElement("div");
-var _dd=_ba.style;
-_dd.visibility="hidden";
-_dd.top=_dd.left=_dd.width="0px";
-_dd.display="inline";
-_dd.cssFloat="left";
-_dd.overflow="visible";
-_dd.opacity="0.999";
-_b8.style.position="absolute";
-_ba.appendChild(_b8);
-_b0.style.marginTop="";
-var _de=_7.getTop(_b0);
-_b0.style.marginTop="0";
-var _df=_7.getTop(_b0);
-_b4=_de-_df;
-_e0();
-_b0.parentNode.insertBefore(_ba,_b0);
-_e1();
-_6.skin(_b8,_2.basePath+"images/bg.png",_b2,_b3);
-_dd.visibility="visible";
-return true;
-}
-return false;
-};
-var _e2=function(){
-var _e3=_2.wmd_env.buttons.split(/\s+/);
-for(var _e4 in _e3){
-switch(_e3[_e4]){
-case "|":
-_cf();
-break;
-case "bold":
-_cd(_8.bold);
-break;
-case "italic":
-_cd(_8.italic);
-break;
-case "link":
-_cd(_8.link);
-break;
-}
-if(_2.full){
-switch(_e3[_e4]){
-case "blockquote":
-_cd(_8.blockquote);
-break;
-case "code":
-_cd(_8.code);
-break;
-case "image":
-_cd(_8.img);
-break;
-case "ol":
-_cd(_8.ol);
-break;
-case "ul":
-_cd(_8.ul);
-break;
-case "heading":
-_cd(_8.h1);
-break;
-case "hr":
-_cd(_8.hr);
-break;
-}
-}
-}
-return;
-};
-var _e5=function(){
-if(/\?noundo/.test(_3.location.href)){
-_2.nativeUndo=true;
-}
-if(!_2.nativeUndo){
-_bd=new _2.undoManager(_b0,function(){
-_b1();
-_db();
-});
-}
-var _e6=_b0.parentNode;
-_b8=_6.makeElement("div");
-_b8.style.display="block";
-_b8.style.zIndex=100;
-if(!_2.full){
-_b8.title+="\n(Free Version)";
-}
-_b8.unselectable="on";
-_b8.onclick=function(){
-_b0.focus();
-};
-_b9=_6.makeElement("span");
-var _e7=_b9.style;
-_e7.height="auto";
-_e7.paddingBottom="2px";
-_e7.lineHeight="0";
-_e7.paddingLeft="15px";
-_e7.paddingRight="65px";
-_e7.display="block";
-_e7.position="absolute";
-_b9.unselectable="on";
-_b8.appendChild(_b9);
-_cd(_8.autoindent);
-var _e8=_6.createImage("images/bg.png");
-var _e9=_6.createImage("images/bg-fill.png");
-_e2();
-_d9();
-if(_bd){
-_d0();
-_be=_d2(_8.undo);
-_bf=_d2(_8.redo);
-var _ea=_5.platform.toLowerCase();
-if(/win/.test(_ea)){
-_be.title+=" - Ctrl+Z";
-_bf.title+=" - Ctrl+Y";
-}else{
-if(/mac/.test(_ea)){
-_be.title+=" - Ctrl+Z";
-_bf.title+=" - Ctrl+Shift+Z";
-}else{
-_be.title+=" - Ctrl+Z";
-_bf.title+=" - Ctrl+Shift+Z";
-}
-}
-}
-var _eb="keydown";
-if(_5.userAgent.indexOf("Opera")!=-1){
-_eb="keypress";
-}
-_6.addEvent(_b0,_eb,function(_ec){
-var _ed=false;
-if(_ec.ctrlKey||_ec.metaKey){
-var _ee=(_ec.charCode||_ec.keyCode);
-var _ef=String.fromCharCode(_ee).toLowerCase();
-for(var _f0 in _c0){
-var _f1=_c0[_f0];
-if(_f1.key&&_ef==_f1.key||_f1.keyCode&&_ec.keyCode==_f1.keyCode){
-_c7(_f1);
-_ed=true;
-}
-}
-}
-if(_ed){
-if(_ec.preventDefault){
-_ec.preventDefault();
-}
-if(_1.event){
-_1.event.returnValue=false;
-}
-}
-});
-_6.addEvent(_b0,"keyup",function(_f2){
-if(_f2.shiftKey&&!_f2.ctrlKey&&!_f2.metaKey){
-var _f3=(_f2.charCode||_f2.keyCode);
-switch(_f3){
-case 13:
-_c7(_8.autoindent);
-break;
-}
-}
-});
-if(!_dc()){
-_bc=_1.setInterval(function(){
-if(_dc()){
-_1.clearInterval(_bc);
-}
-},100);
-}
-_6.addEvent(_1,"resize",_e1);
-_bb=_1.setInterval(_e1,100);
-if(_b0.form){
-var _f4=_b0.form.onsubmit;
-_b0.form.onsubmit=function(){
-_f5();
-if(_f4){
-return _f4.apply(this,arguments);
-}
-};
-}
-_db();
-};
-var _f5=function(){
-if(_2.showdown){
-var _f6=new _2.showdown.converter();
-}
-var _f7=_b0.value;
-var _f8=function(){
-_b0.value=_f7;
-};
-_f7=_6.escapeUnderscores(_f7);
-if(!/markdown/.test(_2.wmd_env.output.toLowerCase())){
-if(_f6){
-_b0.value=_f6.makeHtml(_f7);
-_1.setTimeout(_f8,0);
-}
-}
-return true;
-};
-var _e0=function(){
-var _f9=_6.makeElement("div");
-var _fa=_f9.style;
-_fa.paddingRight="15px";
-_fa.height="100%";
-_fa.display="block";
-_fa.position="absolute";
-_fa.right="0";
-_f9.unselectable="on";
-var _fb=_6.makeElement("a");
-_fa=_fb.style;
-_fa.position="absolute";
-_fa.right="10px";
-_fa.top="5px";
-_fa.display="inline";
-_fa.width="50px";
-_fa.height="25px";
-_fb.href="http://www.wmd-editor.com/";
-_fb.target="_blank";
-_fb.title="WMD: The Wysiwym Markdown Editor";
-var _fc=_6.createImage("images/wmd.png");
-var _fd=_6.createImage("images/wmd-on.png");
-_fb.appendChild(_fc);
-_fb.onmouseover=function(){
-_6.setImage(_fc,"images/wmd-on.png");
-_fb.style.cursor="pointer";
-};
-_fb.onmouseout=function(){
-_6.setImage(_fc,"images/wmd.png");
-};
-_b8.appendChild(_fb);
-};
-var _e1=function(){
-if(!_6.elementOk(_b0)){
-_b8.style.display="none";
-return;
-}
-if(_b8.style.display=="none"){
-_b8.style.display="block";
-}
-var _fe=_7.getWidth(_b0);
-var _ff=_7.getHeight(_b0);
-var _100=_7.getLeft(_b0);
-if(_b8.style.width==_fe+"px"&&_b5==_ff&&_b6==_100){
-if(_7.getTop(_b8)<_7.getTop(_b0)){
-return;
-}
-}
-_b5=_ff;
-_b6=_100;
-var _101=100;
-_b8.style.width=Math.max(_fe,_101)+"px";
-var root=_b8.offsetParent;
-var _103=_7.getHeight(_b9);
-var _104=_103-_b2+"px";
-_b8.style.height=_104;
-if(_6.fillers){
-_6.fillers[0].style.height=_6.fillers[1].style.height=_104;
-}
-var _105=3;
-_b0.style.marginTop=_103+_105+_b4+"px";
-var _106=_7.getTop(_b0);
-var _100=_7.getLeft(_b0);
-_7.setTop(root,_106-_103-_105);
-_7.setLeft(root,_100);
-_b8.style.opacity=_b8.style.opacity||0.999;
-return;
-};
-this.undo=function(){
-if(_bd){
-_bd.undo();
-}
-};
-this.redo=function(){
-if(_bd){
-_bd.redo();
-}
-};
-var init=function(){
-_e5();
-};
-this.destroy=function(){
-if(_bd){
-_bd.destroy();
-}
-if(_ba.parentNode){
-_ba.parentNode.removeChild(_ba);
-}
-if(_b0){
-_b0.style.marginTop="";
-}
-_1.clearInterval(_bb);
-_1.clearInterval(_bc);
-};
-init();
-};
-_2.textareaState=function(_108){
-var _109=this;
-var _10a=function(_10b){
-if(_6.getStyle(_108,"display")=="none"){
-return;
-}
-var _10c=_5.userAgent.indexOf("Opera")!=-1;
-if(_10b.selectionStart!=undefined&&!_10c){
-_10b.focus();
-_10b.selectionStart=_109.start;
-_10b.selectionEnd=_109.end;
-_10b.scrollTop=_109.scrollTop;
-}else{
-if(_3.selection){
-if(_3.activeElement&&_3.activeElement!=_108){
-return;
-}
-_10b.focus();
-var _10d=_10b.createTextRange();
-_10d.moveStart("character",-_10b.value.length);
-_10d.moveEnd("character",-_10b.value.length);
-_10d.moveEnd("character",_109.end);
-_10d.moveStart("character",_109.start);
-_10d.select();
-}
-}
-};
-this.init=function(_10e){
-if(_10e){
-_108=_10e;
-}
-if(_6.getStyle(_108,"display")=="none"){
-return;
-}
-_10f(_108);
-_109.scrollTop=_108.scrollTop;
-if(!_109.text&&_108.selectionStart||_108.selectionStart=="0"){
-_109.text=_108.value;
-}
-};
-var _110=function(_111){
-_111=_111.replace(/\r\n/g,"\n");
-_111=_111.replace(/\r/g,"\n");
-return _111;
-};
-var _10f=function(){
-if(_108.selectionStart||_108.selectionStart=="0"){
-_109.start=_108.selectionStart;
-_109.end=_108.selectionEnd;
-}else{
-if(_3.selection){
-_109.text=_110(_108.value);
-var _112=_3.selection.createRange();
-var _113=_110(_112.text);
-var _114="\x07";
-var _115=_114+_113+_114;
-_112.text=_115;
-var _116=_110(_108.value);
-_112.moveStart("character",-_115.length);
-_112.text=_113;
-_109.start=_116.indexOf(_114);
-_109.end=_116.lastIndexOf(_114)-_114.length;
-var _117=_109.text.length-_110(_108.value).length;
-if(_117){
-_112.moveStart("character",-_113.length);
-while(_117--){
-_113+="\n";
-_109.end+=1;
-}
-_112.text=_113;
-}
-_10a(_108);
-}
-}
-return _109;
-};
-this.restore=function(_118){
-if(!_118){
-_118=_108;
-}
-if(_109.text!=undefined&&_109.text!=_118.value){
-_118.value=_109.text;
-}
-_10a(_118,_109);
-_118.scrollTop=_109.scrollTop;
-};
-this.getChunks=function(){
-var _119=new _2.Chunks();
-_119.before=_110(_109.text.substring(0,_109.start));
-_119.startTag="";
-_119.selection=_110(_109.text.substring(_109.start,_109.end));
-_119.endTag="";
-_119.after=_110(_109.text.substring(_109.end));
-_119.scrollTop=_109.scrollTop;
-return _119;
-};
-this.setChunks=function(_11a){
-_11a.before=_11a.before+_11a.startTag;
-_11a.after=_11a.endTag+_11a.after;
-var _11b=_5.userAgent.indexOf("Opera")!=-1;
-if(_11b){
-_11a.before=_11a.before.replace(/\n/g,"\r\n");
-_11a.selection=_11a.selection.replace(/\n/g,"\r\n");
-_11a.after=_11a.after.replace(/\n/g,"\r\n");
-}
-_109.start=_11a.before.length;
-_109.end=_11a.before.length+_11a.selection.length;
-_109.text=_11a.before+_11a.selection+_11a.after;
-_109.scrollTop=_11a.scrollTop;
-};
-this.init();
-};
-_2.Chunks=function(){
-};
-_2.Chunks.prototype.findTags=function(_11c,_11d){
-var _11e,_11f;
-var _120=this;
-if(_11c){
-_11f=_6.regexToString(_11c);
-_11e=new _4(_11f.expression+"$",_11f.flags);
-this.before=this.before.replace(_11e,function(_121){
-_120.startTag=_120.startTag+_121;
-return "";
-});
-_11e=new _4("^"+_11f.expression,_11f.flags);
-this.selection=this.selection.replace(_11e,function(_122){
-_120.startTag=_120.startTag+_122;
-return "";
-});
-}
-if(_11d){
-_11f=_6.regexToString(_11d);
-_11e=new _4(_11f.expression+"$",_11f.flags);
-this.selection=this.selection.replace(_11e,function(_123){
-_120.endTag=_123+_120.endTag;
-return "";
-});
-_11e=new _4("^"+_11f.expression,_11f.flags);
-this.after=this.after.replace(_11e,function(_124){
-_120.endTag=_124+_120.endTag;
-return "";
-});
-}
-};
-_2.Chunks.prototype.trimWhitespace=function(_125){
-this.selection=this.selection.replace(/^(\s*)/,"");
-if(!_125){
-this.before+=_4.$1;
-}
-this.selection=this.selection.replace(/(\s*)$/,"");
-if(!_125){
-this.after=_4.$1+this.after;
-}
-};
-_2.Chunks.prototype.skipLines=function(_126,_127,_128){
-if(_126==undefined){
-_126=1;
-}
-if(_127==undefined){
-_127=1;
-}
-_126++;
-_127++;
-var _129,_12a;
-this.selection=this.selection.replace(/(^\n*)/,"");
-this.startTag=this.startTag+_4.$1;
-this.selection=this.selection.replace(/(\n*$)/,"");
-this.endTag=this.endTag+_4.$1;
-this.startTag=this.startTag.replace(/(^\n*)/,"");
-this.before=this.before+_4.$1;
-this.endTag=this.endTag.replace(/(\n*$)/,"");
-this.after=this.after+_4.$1;
-if(this.before){
-_129=_12a="";
-while(_126--){
-_129+="\\n?";
-_12a+="\n";
-}
-if(_128){
-_129="\\n*";
-}
-this.before=this.before.replace(new _4(_129+"$",""),_12a);
-}
-if(this.after){
-_129=_12a="";
-while(_127--){
-_129+="\\n?";
-_12a+="\n";
-}
-if(_128){
-_129="\\n*";
-}
-this.after=this.after.replace(new _4(_129,""),_12a);
-}
-};
-_8.prefixes="(?:\\s{4,}|\\s*>|\\s*-\\s+|\\s*\\d+\\.|=|\\+|-|_|\\*|#|\\s*\\[[^\n]]+\\]:)";
-_8.unwrap=function(_12b){
-var _12c=new _4("([^\\n])\\n(?!(\\n|"+_8.prefixes+"))","g");
-_12b.selection=_12b.selection.replace(_12c,"$1 $2");
-};
-_8.wrap=function(_12d,len){
-_8.unwrap(_12d);
-var _12f=new _4("(.{1,"+len+"})( +|$\\n?)","gm");
-_12d.selection=_12d.selection.replace(_12f,function(_130,line){
-if(new _4("^"+_8.prefixes,"").test(_130)){
-return _130;
-}
-return line+"\n";
-});
-_12d.selection=_12d.selection.replace(/\s+$/,"");
-};
-_8.doBold=function(_132){
-return _8.doBorI(_132,2,"strong text");
-};
-_8.doItalic=function(_133){
-return _8.doBorI(_133,1,"emphasized text");
-};
-_8.doBorI=function(_134,_135,_136){
-_134.trimWhitespace();
-_134.selection=_134.selection.replace(/\n{2,}/g,"\n");
-_134.before.search(/(\**$)/);
-var _137=_4.$1;
-_134.after.search(/(^\**)/);
-var _138=_4.$1;
-var _139=Math.min(_137.length,_138.length);
-if((_139>=_135)&&(_139!=2||_135!=1)){
-_134.before=_134.before.replace(_4("[*]{"+_135+"}$",""),"");
-_134.after=_134.after.replace(_4("^[*]{"+_135+"}",""),"");
-return;
-}
-if(!_134.selection&&_138){
-_134.after=_134.after.replace(/^([*_]*)/,"");
-_134.before=_134.before.replace(/(\s?)$/,"");
-var _13a=_4.$1;
-_134.before=_134.before+_138+_13a;
-return;
-}
-if(!_134.selection&&!_138){
-_134.selection=_136;
-}
-var _13b=_135<=1?"*":"**";
-_134.before=_134.before+_13b;
-_134.after=_13b+_134.after;
-};
-_8.stripLinkDefs=function(_13c,_13d){
-_13c=_13c.replace(/^[ ]{0,3}\[(\d+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|$)/gm,function(_13e,id,_140,_141,_142){
-_13d[id]=_13e.replace(/\s*$/,"");
-if(_141){
-_13d[id]=_13e.replace(/["(](.+?)[")]$/,"");
-return _141+_142;
-}
-return "";
-});
-return _13c;
-};
-_8.addLinkDef=function(_143,_144){
-var _145=0;
-var _146={};
-_143.before=_8.stripLinkDefs(_143.before,_146);
-_143.selection=_8.stripLinkDefs(_143.selection,_146);
-_143.after=_8.stripLinkDefs(_143.after,_146);
-var _147="";
-var _148=/(\[(?:\[[^\]]*\]|[^\[\]])*\][ ]?(?:\n[ ]*)?\[)(\d+)(\])/g;
-var _149=function(def){
-_145++;
-def=def.replace(/^[ ]{0,3}\[(\d+)\]:/,"  ["+_145+"]:");
-_147+="\n"+def;
-};
-var _14b=function(_14c,_14d,id,end){
-if(_146[id]){
-_149(_146[id]);
-return _14d+_145+end;
-}
-return _14c;
-};
-_143.before=_143.before.replace(_148,_14b);
-if(_144){
-_149(_144);
-}else{
-_143.selection=_143.selection.replace(_148,_14b);
-}
-var _150=_145;
-_143.after=_143.after.replace(_148,_14b);
-if(_143.after){
-_143.after=_143.after.replace(/\n*$/,"");
-}
-if(!_143.after){
-_143.selection=_143.selection.replace(/\n*$/,"");
-}
-_143.after+="\n\n"+_147;
-return _150;
-};
-_8.doLinkOrImage=function(_151,_152,_153){
-_151.trimWhitespace();
-_151.findTags(/\s*!?\[/,/\][ ]?(?:\n[ ]*)?(\[.*?\])?/);
-if(_151.endTag.length>1){
-_151.startTag=_151.startTag.replace(/!?\[/,"");
-_151.endTag="";
-_8.addLinkDef(_151,null);
-}else{
-if(/\n\n/.test(_151.selection)){
-_8.addLinkDef(_151,null);
-return;
-}
-var _154;
-var _155=function(_156){
-if(_156!=null){
-_151.startTag=_151.endTag="";
-var _157=" [999]: "+_156;
-var num=_8.addLinkDef(_151,_157);
-_151.startTag=_152?"![":"[";
-_151.endTag="]["+num+"]";
-if(!_151.selection){
-if(_152){
-_151.selection="alt text";
-}else{
-_151.selection="link text";
-}
-}
-}
-_153();
-};
-if(_152){
-_154=_6.prompt("<p style='margin-top: 0px'><b>Enter the image URL.</b></p><p>You can also add a title, which will be displayed as a tool tip.</p><p>Example:<br />http://wmd-editor.com/images/cloud1.jpg   \"Optional title\"</p>","http://",_155);
-}else{
-_154=_6.prompt("<p style='margin-top: 0px'><b>Enter the web address.</b></p><p>You can also add a title, which will be displayed as a tool tip.</p><p>Example:<br />http://wmd-editor.com/   \"Optional title\"</p>","http://",_155);
-}
-return true;
-}
-};
-_8.bold={};
-_8.bold.description="Strong <strong>";
-_8.bold.image="images/bold.png";
-_8.bold.key="b";
-_8.bold.textOp=_8.doBold;
-_8.italic={};
-_8.italic.description="Emphasis <em>";
-_8.italic.image="images/italic.png";
-_8.italic.key="i";
-_8.italic.textOp=_8.doItalic;
-_8.link={};
-_8.link.description="Hyperlink <a>";
-_8.link.image="images/link.png";
-_8.link.key="l";
-_8.link.textOp=function(_159,_15a){
-return _8.doLinkOrImage(_159,false,_15a);
-};
-_8.undo={};
-_8.undo.description="Undo";
-_8.undo.image="images/undo.png";
-_8.undo.execute=function(_15b){
-_15b.undo();
-};
-_8.redo={};
-_8.redo.description="Redo";
-_8.redo.image="images/redo.png";
-_8.redo.execute=function(_15c){
-_15c.redo();
-};
-_6.findPanes=function(_15d){
-_15d.preview=_15d.preview||_6.getElementsByClass("wmd-preview",null,"div")[0];
-_15d.output=_15d.output||_6.getElementsByClass("wmd-output",null,"textarea")[0];
-_15d.output=_15d.output||_6.getElementsByClass("wmd-output",null,"div")[0];
-if(!_15d.input){
-var _15e=-1;
-var _15f=_3.getElementsByTagName("textarea");
-for(var _160=0;_160<_15f.length;_160++){
-var _161=_15f[_160];
-if(_161!=_15d.output&&!/wmd-ignore/.test(_161.className.toLowerCase())){
-_15d.input=_161;
-break;
-}
-}
-}
-return _15d;
-};
-_6.makeAPI=function(){
-_2.wmd={};
-_2.wmd.editor=_2.editor;
-_2.wmd.previewManager=_2.previewManager;
-};
-_6.startEditor=function(){
-if(_2.wmd_env.autostart==false){
-_2.editorInit();
-_6.makeAPI();
-return;
-}
-var _162={};
-var _163,_164;
-var _165=function(){
-try{
-var _166=_6.cloneObject(_162);
-_6.findPanes(_162);
-if(!_6.objectsEqual(_166,_162)&&_162.input){
-if(!_163){
-_2.editorInit();
-var _167;
-if(_2.previewManager!=undefined){
-_164=new _2.previewManager(_162);
-_167=_164.refresh;
-}
-_163=new _2.editor(_162.input,_167);
-}else{
-if(_164){
-_164.refresh(true);
-}
-}
-}
-}
-catch(e){
-}
-};
-_6.addEvent(_1,"load",_165);
-var _168=_1.setInterval(_165,100);
-};
-_2.previewManager=function(_169){
-var _16a=this;
-var _16b,_16c;
-var _16d,_16e;
-var _16f,_170;
-var _171=3000;
-var _172="delayed";
-var _173=function(_174,_175){
-_6.addEvent(_174,"input",_175);
-_174.onpaste=_175;
-_174.ondrop=_175;
-_6.addEvent(_1,"keypress",_175);
-_6.addEvent(_174,"keypress",_175);
-_6.addEvent(_174,"keydown",_175);
-_16c=new _2.inputPoller(_174,_175);
-};
-var _176=function(){
-var _177=0;
-if(_1.innerHeight){
-_177=_1.pageYOffset;
-}else{
-if(_3.documentElement&&_3.documentElement.scrollTop){
-_177=_3.documentElement.scrollTop;
-}else{
-if(_3.body){
-_177=_3.body.scrollTop;
-}
-}
-}
-return _177;
-};
-var _178=function(){
-if(!_169.preview&&!_169.output){
-return;
-}
-var text=_169.input.value;
-if(text&&text==_16f){
-return;
-}else{
-_16f=text;
-}
-var _17a=new Date().getTime();
-if(!_16b&&_2.showdown){
-_16b=new _2.showdown.converter();
-}
-text=_6.escapeUnderscores(text);
-if(_16b){
-text=_16b.makeHtml(text);
-}
-var _17b=new Date().getTime();
-_16e=_17b-_17a;
-_17c(text);
-_170=text;
-};
-var _17d=function(){
-if(_16d){
-_1.clearTimeout(_16d);
-_16d=undefined;
-}
-if(_172!="manual"){
-var _17e=0;
-if(_172=="delayed"){
-_17e=_16e;
-}
-if(_17e>_171){
-_17e=_171;
-}
-_16d=_1.setTimeout(_178,_17e);
-}
-};
-var _17f;
-var _180;
-var _181=function(_182){
-if(_182.scrollHeight<=_182.clientHeight){
-return 1;
-}
-return _182.scrollTop/(_182.scrollHeight-_182.clientHeight);
-};
-var _183=function(_184,_185){
-_184.scrollTop=(_184.scrollHeight-_184.clientHeight)*_185;
-};
-var _186=function(){
-if(_169.preview){
-_17f=_181(_169.preview);
-}
-if(_169.output){
-_180=_181(_169.output);
-}
-};
-var _187=function(){
-if(_169.preview){
-_169.preview.scrollTop=_169.preview.scrollTop;
-_183(_169.preview,_17f);
-}
-if(_169.output){
-_183(_169.output,_180);
-}
-};
-this.refresh=function(_188){
-if(_188){
-_16f="";
-_178();
-}else{
-_17d();
-}
-};
-this.processingTime=function(){
-return _16e;
-};
-this.output=function(){
-return _170;
-};
-this.setUpdateMode=function(_189){
-_172=_189;
-_16a.refresh();
-};
-var _18a=true;
-var _17c=function(text){
-_186();
-var _18c=_7.getTop(_169.input)-_176();
-if(_169.output){
-if(_169.output.value!=undefined){
-_169.output.value=text;
-_169.output.readOnly=true;
-}else{
-var _18d=text.replace(/&/g,"&amp;");
-_18d=_18d.replace(/</g,"&lt;");
-_169.output.innerHTML="<pre><code>"+_18d+"</code></pre>";
-}
-}
-if(_169.preview){
-_169.preview.innerHTML=text;
-}
-_187();
-if(_18a){
-_18a=false;
-return;
-}
-var _18e=_7.getTop(_169.input)-_176();
-if(_5.userAgent.indexOf("MSIE")!=-1){
-_1.setTimeout(function(){
-_1.scrollBy(0,_18e-_18c);
-},0);
-}else{
-_1.scrollBy(0,_18e-_18c);
-}
-};
-var init=function(){
-_173(_169.input,_17d);
-_178();
-if(_169.preview){
-_169.preview.scrollTop=0;
-}
-if(_169.output){
-_169.output.scrollTop=0;
-}
-};
-this.destroy=function(){
-if(_16c){
-_16c.destroy();
-}
-};
-init();
-};
-};
-if(Attacklab.fileLoaded){
-Attacklab.fileLoaded("wmd-base.js");
-}
-
--- a/site-media/scripts/wmd/wmd-plus.js	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,311 +0,0 @@
-var Attacklab=Attacklab||{};
-Attacklab.wmdPlus=function(){
-this.symboltable;
-var _1=top;
-var _2=_1["Attacklab"];
-var _3=_1["document"];
-var _4=_1["RegExp"];
-var _5=_1["navigator"];
-var _6=_2.Util;
-var _7=_2.Position;
-var _8=_2.Command;
-_8.doAutoindent=function(_9){
-_9.before=_9.before.replace(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]*\n$/,"\n\n");
-_9.before=_9.before.replace(/(\n|^)[ ]{0,3}>[ \t]*\n$/,"\n\n");
-_9.before=_9.before.replace(/(\n|^)[ \t]+\n$/,"\n\n");
-if(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]+.*\n$/.test(_9.before)){
-if(_8.doList){
-_8.doList(_9);
-}
-}
-if(/(\n|^)[ ]{0,3}>[ \t]+.*\n$/.test(_9.before)){
-if(_8.doBlockquote){
-_8.doBlockquote(_9);
-}
-}
-if(/(\n|^)(\t|[ ]{4,}).*\n$/.test(_9.before)){
-if(_8.doCode){
-_8.doCode(_9);
-}
-}
-};
-_8.doBlockquote=function(_a){
-_a.selection=_a.selection.replace(/^(\n*)([^\r]+?)(\n*)$/,function(_b,_c,_d,_e){
-_a.before+=_c;
-_a.after=_e+_a.after;
-return _d;
-});
-_a.before=_a.before.replace(/(>[ \t]*)$/,function(_f,_10){
-_a.selection=_10+_a.selection;
-return "";
-});
-_a.selection=_a.selection.replace(/^(\s|>)+$/,"");
-_a.selection=_a.selection||"Blockquote";
-if(_a.before){
-_a.before=_a.before.replace(/\n?$/,"\n");
-}
-if(_a.after){
-_a.after=_a.after.replace(/^\n?/,"\n");
-}
-_a.before=_a.before.replace(/(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*$)/,function(_11){
-_a.startTag=_11;
-return "";
-});
-_a.after=_a.after.replace(/^(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*)/,function(_12){
-_a.endTag=_12;
-return "";
-});
-var _13=function(_14){
-var _15=_14?"> ":"";
-if(_a.startTag){
-_a.startTag=_a.startTag.replace(/\n((>|\s)*)\n$/,function(_16,_17){
-return "\n"+_17.replace(/^[ ]{0,3}>?[ \t]*$/gm,_15)+"\n";
-});
-}
-if(_a.endTag){
-_a.endTag=_a.endTag.replace(/^\n((>|\s)*)\n/,function(_18,_19){
-return "\n"+_19.replace(/^[ ]{0,3}>?[ \t]*$/gm,_15)+"\n";
-});
-}
-};
-if(/^(?![ ]{0,3}>)/m.test(_a.selection)){
-_8.wrap(_a,_2.wmd_env.lineLength-2);
-_a.selection=_a.selection.replace(/^/gm,"> ");
-_13(true);
-_a.skipLines();
-}else{
-_a.selection=_a.selection.replace(/^[ ]{0,3}> ?/gm,"");
-_8.unwrap(_a);
-_13(false);
-if(!/^(\n|^)[ ]{0,3}>/.test(_a.selection)){
-if(_a.startTag){
-_a.startTag=_a.startTag.replace(/\n{0,2}$/,"\n\n");
-}
-}
-if(!/(\n|^)[ ]{0,3}>.*$/.test(_a.selection)){
-if(_a.endTag){
-_a.endTag=_a.endTag.replace(/^\n{0,2}/,"\n\n");
-}
-}
-}
-if(!/\n/.test(_a.selection)){
-_a.selection=_a.selection.replace(/^(> *)/,function(_1a,_1b){
-_a.startTag+=_1b;
-return "";
-});
-}
-};
-_8.doCode=function(_1c){
-var _1d=/\S[ ]*$/.test(_1c.before);
-var _1e=/^[ ]*\S/.test(_1c.after);
-if((!_1e&&!_1d)||/\n/.test(_1c.selection)){
-_1c.before=_1c.before.replace(/[ ]{4}$/,function(_1f){
-_1c.selection=_1f+_1c.selection;
-return "";
-});
-var _20=1;
-var _21=1;
-if(/\n(\t|[ ]{4,}).*\n$/.test(_1c.before)){
-_20=0;
-}
-if(/^\n(\t|[ ]{4,})/.test(_1c.after)){
-_21=0;
-}
-_1c.skipLines(_20,_21);
-if(!_1c.selection){
-_1c.startTag="    ";
-_1c.selection="print(\"code sample\");";
-return;
-}
-if(/^[ ]{0,3}\S/m.test(_1c.selection)){
-_1c.selection=_1c.selection.replace(/^/gm,"    ");
-}else{
-_1c.selection=_1c.selection.replace(/^[ ]{4}/gm,"");
-}
-}else{
-_1c.trimWhitespace();
-_1c.findTags(/`/,/`/);
-if(!_1c.startTag&&!_1c.endTag){
-_1c.startTag=_1c.endTag="`";
-if(!_1c.selection){
-_1c.selection="print(\"code sample\");";
-}
-}else{
-if(_1c.endTag&&!_1c.startTag){
-_1c.before+=_1c.endTag;
-_1c.endTag="";
-}else{
-_1c.startTag=_1c.endTag="";
-}
-}
-}
-};
-_8.autoindent={};
-_8.autoindent.textOp=_8.doAutoindent;
-_8.blockquote={};
-_8.blockquote.description="Blockquote <blockquote>";
-_8.blockquote.image="images/blockquote.png";
-_8.blockquote.key=".";
-_8.blockquote.keyCode=190;
-_8.blockquote.textOp=function(_22){
-return _8.doBlockquote(_22);
-};
-_8.code={};
-_8.code.description="Code Sample <pre><code>";
-_8.code.image="images/code.png";
-_8.code.key="k";
-_8.code.textOp=_8.doCode;
-_8.img={};
-_8.img.description="Image <img>";
-_8.img.image="images/img.png";
-_8.img.key="g";
-_8.img.textOp=function(_23,_24){
-return _8.doLinkOrImage(_23,true,_24);
-};
-_8.doList=function(_25,_26){
-var _27=/(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*/;
-var _28="";
-var _29=1;
-var _2a=function(){
-if(_26){
-var _2b=" "+_29+". ";
-_29++;
-return _2b;
-}
-var _2c=_28||"-";
-return "  "+_2c+" ";
-};
-var _2d=function(_2e){
-if(_26==undefined){
-_26=/^\s*\d/.test(_2e);
-}
-_2e=_2e.replace(/^[ ]{0,3}([*+-]|\d+[.])\s/gm,function(_2f){
-return _2a();
-});
-return _2e;
-};
-var _30=function(){
-_31=_6.regexToString(_27);
-_31.expression="^\n*"+_31.expression;
-var _32=_6.stringToRegex(_31);
-_25.after=_25.after.replace(_32,_2d);
-};
-_25.findTags(/(\n|^)*[ ]{0,3}([*+-]|\d+[.])\s+/,null);
-var _33=/^\n/;
-if(_25.before&&!/\n$/.test(_25.before)&&!_33.test(_25.startTag)){
-_25.before+=_25.startTag;
-_25.startTag="";
-}
-if(_25.startTag){
-var _34=/\d+[.]/.test(_25.startTag);
-_25.startTag="";
-_25.selection=_25.selection.replace(/\n[ ]{4}/g,"\n");
-_8.unwrap(_25);
-_25.skipLines();
-if(_34){
-_30();
-}
-if(_26==_34){
-return;
-}
-}
-var _35=1;
-var _31=_6.regexToString(_27);
-_31.expression="(\\n|^)"+_31.expression+"$";
-var _36=_6.stringToRegex(_31);
-_25.before=_25.before.replace(_36,function(_37){
-if(/^\s*([*+-])/.test(_37)){
-_28=_4.$1;
-}
-_35=/[^\n]\n\n[^\n]/.test(_37)?1:0;
-return _2d(_37);
-});
-if(!_25.selection){
-_25.selection="List item";
-}
-var _38=_2a();
-var _39=1;
-_31=_6.regexToString(_27);
-_31.expression="^\n*"+_31.expression;
-_36=_6.stringToRegex(_31);
-_25.after=_25.after.replace(_36,function(_3a){
-_39=/[^\n]\n\n[^\n]/.test(_3a)?1:0;
-return _2d(_3a);
-});
-_25.trimWhitespace(true);
-_25.skipLines(_35,_39,true);
-_25.startTag=_38;
-var _3b=_38.replace(/./g," ");
-_8.wrap(_25,_2.wmd_env.lineLength-_3b.length);
-_25.selection=_25.selection.replace(/\n/g,"\n"+_3b);
-};
-_8.doHeading=function(_3c){
-_3c.selection=_3c.selection.replace(/\s+/g," ");
-_3c.selection=_3c.selection.replace(/(^\s+|\s+$)/g,"");
-var _3d=0;
-_3c.findTags(/#+[ ]*/,/[ ]*#+/);
-if(/#+/.test(_3c.startTag)){
-_3d=_4.lastMatch.length;
-}
-_3c.startTag=_3c.endTag="";
-_3c.findTags(null,/\s?(-+|=+)/);
-if(/=+/.test(_3c.endTag)){
-_3d=1;
-}
-if(/-+/.test(_3c.endTag)){
-_3d=2;
-}
-_3c.startTag=_3c.endTag="";
-_3c.skipLines(1,1);
-if(!_3c.selection){
-_3c.startTag="## ";
-_3c.selection="Heading";
-_3c.endTag=" ##";
-return;
-}
-var _3e=_3d==0?2:_3d-1;
-if(_3e){
-var _3f=_3e>=2?"-":"=";
-var _40=_3c.selection.length;
-if(_40>_2.wmd_env.lineLength){
-_40=_2.wmd_env.lineLength;
-}
-_3c.endTag="\n";
-while(_40--){
-_3c.endTag+=_3f;
-}
-}
-};
-_8.ol={};
-_8.ol.description="Numbered List <ol>";
-_8.ol.image="images/ol.png";
-_8.ol.key="o";
-_8.ol.textOp=function(_41){
-_8.doList(_41,true);
-};
-_8.ul={};
-_8.ul.description="Bulleted List <ul>";
-_8.ul.image="images/ul.png";
-_8.ul.key="u";
-_8.ul.textOp=function(_42){
-_8.doList(_42,false);
-};
-_8.h1={};
-_8.h1.description="Heading <h1>/<h2>";
-_8.h1.image="images/h1.png";
-_8.h1.key="h";
-_8.h1.textOp=_8.doHeading;
-_8.hr={};
-_8.hr.description="Horizontal Rule <hr>";
-_8.hr.image="images/hr.png";
-_8.hr.key="r";
-_8.hr.textOp=function(_43){
-_43.startTag="----------\n";
-_43.selection="";
-_43.skipLines(2,1,true);
-};
-};
-if(Attacklab.fileLoaded){
-Attacklab.fileLoaded("wmd-plus.js");
-}
-
--- a/site-media/scripts/wmd/wmd.js	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-var Attacklab=Attacklab||{};
-Attacklab.wmd_env={};
-Attacklab.account_options={};
-Attacklab.wmd_defaults={version:1,output:"HTML",lineLength:40,delayLoad:false};
-if(!Attacklab.wmd){
-Attacklab.wmd=function(){
-Attacklab.loadEnv=function(){
-var _1=function(_2){
-if(!_2){
-return;
-}
-for(var _3 in _2){
-Attacklab.wmd_env[_3]=_2[_3];
-}
-};
-_1(Attacklab.wmd_defaults);
-_1(Attacklab.account_options);
-_1(top["wmd_options"]);
-Attacklab.full=true;
-var _4="bold italic | link blockquote code image | ol ul heading hr";
-Attacklab.wmd_env.buttons=Attacklab.wmd_env.buttons||_4;
-};
-Attacklab.loadEnv();
-var _5=["showdown.js","wmd-base.js","wmd-plus.js"];
-var _6=function(_7){
-};
-Attacklab.fileLoaded=function(_8){
-arguments.callee.count=arguments.callee.count||0;
-if(++arguments.callee.count>=_5.length){
-var go=function(){
-Attacklab.wmdBase();
-Attacklab.Util.startEditor();
-};
-if(Attacklab.wmd_env.delayLoad){
-window.setTimeout(go,0);
-}else{
-go();
-}
-}
-};
-Attacklab.editorInit=function(){
-Attacklab.wmdPlus();
-};
-var _a=function(_b,_c){
-var _d=Attacklab.basePath+_b;
-if(_c){
-_d+="?nocache="+(new Date()).getTime();
-}
-var _e=document.createElement("script");
-_e.src=_d;
-top.document.documentElement.firstChild.appendChild(_e);
-};
-var _f=function(_10){
-var _11=RegExp("(.*)"+_10+"(\\?(.+))?$","g");
-var _12=document.getElementsByTagName("script");
-for(var i=0;i<_12.length;i++){
-if(_11.test(_12[i].src)){
-var _14=RegExp.$1;
-if(/wmd-editor.com/.test(_12[i].src)){
-return null;
-}
-return _14;
-}
-}
-};
-Attacklab.basePath=_f("wmd.js")||"http://static.wmd-editor.com/v2/";
-for(var f,i=0;f=_5[i];i++){
-_a(f,false);
-}
-};
-Attacklab.wmd();
-}
-
--- a/site-media/style/aal.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/* 
-  aardvark.legs by Anatoli Papirovski - http://fecklessmind.com/
-  Licensed under the MIT license. http://www.opensource.org/licenses/mit-license.php
-*/
-
-/* 
-  Reset first. Modified version of Eric Meyer and Paul Chaplin reset 
-  from http://meyerweb.com/eric/tools/css/reset/ 
-*/
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, font, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-header, nav, section, article, aside, footer
-{border: 0; margin: 0; outline: 0; padding: 0; background: transparent; vertical-align: baseline;}
-
-blockquote, q {quotes: none;}
-blockquote:before,blockquote:after,q:before,q:after {content: ''; content: none;}
-
-header, nav, section, article, aside, footer {display: block;}
-
-/* Basic styles */
-body {background: #fff; color: #000; font: 0.875em/1.5em "Helvetica Neue", Helvetica, Arial, "Liberation Sans", "Bitstream Vera Sans", sans-serif;}
-html>body {font-size: 14px;}
-
-img {display: inline-block; vertical-align: bottom;}
-
-h1,h2,h3,h4,h5,h6,strong,b,dt,th {font-weight: 700;}
-address,cite,em,i,caption,dfn,var {font-style: italic;}
-
-h1 {margin: 0 0 0.75em; font-size: 2em;}
-h2 {margin: 0 0 1em; font-size: 1.5em;}
-h3 {margin: 0 0 1.286em; font-size: 1.167em;}
-h4 {margin: 0 0 1.5em; font-size: 1em;}
-h5 {margin: 0 0 1.8em; font-size: .834em;}
-h6 {margin: 0 0 2em; font-size: .75em;}
-
-p,ul,ol,dl,blockquote,pre {margin: 0 0 1.5em;}
-
-li ul,li ol {margin: 0;}
-ul {list-style: outside disc;}
-ol {list-style: outside decimal;}
-li {margin: 0 0 0 2em;}
-dd {padding-left: 1.5em;}
-blockquote {padding: 0 1.5em;}
-blockquote p:last-child {margin-bottom: 0em;}
-
-a {text-decoration: underline;}
-a:hover {text-decoration: none;}
-abbr,acronym {border-bottom: 1px dotted; cursor: help;}
-del {text-decoration: line-through;}
-ins {text-decoration: overline;}
-sub {font-size: .834em; line-height: 1em; vertical-align: sub;}
-sup {font-size: .834em; line-height: 1em; vertical-align: super;}
-
-tt,code,kbd,samp,pre {font-size: 0.8em; line-height: 1.875em; font-family: "Monaco", "Consolas", "Courier New", Courier, monospace;}
-
-/* Table styles */
-table {border-collapse: collapse; border-spacing: 0; margin: 0 0 1.5em;}
-caption {text-align: left;}
-th, td {padding: .25em .5em;}
-tbody td, tbody th {border: 1px solid #000;}
-tfoot {font-style: italic;}
-
-/* Form styles */
-fieldset {clear: both;}
-legend {padding: 0 0 1.286em; font-size: 1.167em; font-weight: 700;}
-fieldset fieldset legend {padding: 0 0 1.5em; font-size: 1em;}
-* html legend {margin-left: -7px;}
-*+html legend {margin-left: -7px;}
-
-form .field, form .buttons {clear: both; margin: 0 0 1.5em;}
-form .field label {display: block;}
-form ul.fields li {list-style-type: none; margin: 0;}
-form ul.inline li, form ul.inline label {display: inline;}
-form ul.inline li {padding: 0 .75em 0 0;}
-
-input.radio, input.checkbox {vertical-align: top;}
-label, button, input.submit, input.image {cursor: pointer;}
-* html input.radio, * html input.checkbox {vertical-align: middle;}
-*+html input.radio, *+html input.checkbox {vertical-align: middle;}
-
-textarea {overflow: auto;}
-input.text, input.password, textarea, select {margin: 0; font: 1em/1.3 Helvetica, Arial, "Liberation Sans", "Bitstream Vera Sans", sans-serif; vertical-align: baseline;}
-input.text, input.password, textarea {border: 1px solid #444; border-bottom-color: #666; border-right-color: #666; padding: 2px;}
-
-* html button {margin: 0 .34em 0 0;}
-*+html button {margin: 0 .34em 0 0;}
-
-form.horizontal .field {padding-left: 150px;}
-form.horizontal .field label {display: inline; float: left; width: 140px; margin-left: -150px;}
-
-/* Useful classes */
-img.left {display: inline; float: left; margin: 0 1.5em .75em 0;}
-img.right {display: inline; float: right; margin: 0 0 .75em .75em;}
\ No newline at end of file
--- a/site-media/style/blog.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/* @override http://localhost:8000/site-media/style/blog.css */
-div#blog-entry-date {
-    color: #666;
-}
-div.blog-list-entry {
-    border-bottom: 1px solid #eee;
-    height: 3em;
-    line-height: 3em;
-    -webkit-text-size-adjust: none;
-}
-h2.blog-list-entry-title {
-    display: inline;
-}
-p.blog-list-entry-snip {
-    display: inline;
-    padding-left: 1em;
-    color: #666;
-}
-h2#blog-list-older, h2#blog-list-newer {
-    display: inline;
-}
-h2#blog-list-newer {
-    float: right;
-}
-div#blog-list-nav {
-    border: 0px;
-    margin-left: -1.5em;
-}
-
-div#blog-entry {
-    margin-bottom: 1.5em;
-}
-div#blog-entry img {
-    border: 1px solid #000;
-    display: block;
-    margin-left: auto;
-    margin-right: auto;
-}
-div#blog-entry div.no-img-borders img {
-    border: none;
-}
-
-div#blog-entry-comments {
-    margin-top: 1.5em;
-    margin-bottom: 1.5em;
-}
-div#blog-entry-new-comment {
-    margin-top: 1.5em;
-}
-
-div.blog-entry-comment-body {
-    margin-left: 2em;
-}
-div.wmd-preview {
-    margin-left: 2em;
-}
-div.blog-entry-comment-body h1, .wmd-preview h1 {
-    font-size: 1.4em;
-}
-div.blog-entry-comment-body h2, .wmd-preview h2 {
-    font-size: 1.3em;
-}
-div.blog-entry-comment-body h3, .wmd-preview h3, div.blog-entry-comment-body h4, .wmd-preview h4, div.blog-entry-comment-body h5, .wmd-preview h5, div.blog-entry-comment-body h6, .wmd-preview h6 {
-    font-size: 1.2em;
-}
-
-form#blog-new-comment-form textarea {
-    width: 100%;
-}
-input#blog-new-comment-name {
-    width: 40%;
-    margin-right: 1em;
-    border: 1px solid #111;
-}
-input#blog-new-comment-submit {
-    margin-top: 1em;
-}
-p#blog-new-comment-body-area {
-    margin-bottom: 0em;
-}
-p#blog-new-comment-instructions {
-    margin-top: 0em;
-}
-span#blog-new-comment-invalid-body {
-    float: right;
-}
-#blog-new-comment-name-area label.invalid {
-    display: inline;
-}
-#blog-new-comment-body-area label.invalid {
-    float: right;
-}
-div#blog-entry img.blog-photo-inline-left {
-    float: left;
-	margin-right:  1.5em;
-}
-div#blog-entry img.blog-photo-inline-right {
-    float: right;
-	margin-left: 1.5em;
-}
-h2 + p .blog-photo-inline-left {
-	margin-top:  1em;
-}
-div.blog-entry-comment-body pre {
-    font-size: 1em;
-    line-height: 1.5em;
-}
--- a/site-media/style/blueprint/ie.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/* -----------------------------------------------------------------------
-
-
- Blueprint CSS Framework 0.8
- http://blueprintcss.org
-
-   * Copyright (c) 2007-Present. See LICENSE for more info.
-   * See README for instructions on how to use Blueprint.
-   * For credits and origins, see AUTHORS.
-   * This is a compressed file. See the sources in the 'src' directory.
-
------------------------------------------------------------------------ */
-
-/* ie.css */
-body {text-align:center;}
-.container {text-align:left;}
-* html .column, * html div.span-1, * html div.span-2, * html div.span-3, * html div.span-4, * html div.span-5, * html div.span-6, * html div.span-7, * html div.span-8, * html div.span-9, * html div.span-10, * html div.span-11, * html div.span-12, * html div.span-13, * html div.span-14, * html div.span-15, * html div.span-16, * html div.span-17, * html div.span-18, * html div.span-19, * html div.span-20, * html div.span-21, * html div.span-22, * html div.span-23, * html div.span-24 {overflow-x:hidden;}
-* html legend {margin:-18px -8px 16px 0;padding:0;}
-ol {margin-left:2em;}
-sup {vertical-align:text-top;}
-sub {vertical-align:text-bottom;}
-html>body p code {*white-space:normal;}
-hr {margin:-8px auto 11px;}
-.clearfix, .container {display:inline-block;}
-* html .clearfix, * html .container {height:1%;}
-fieldset {padding-top:0;}
\ No newline at end of file
--- a/site-media/style/blueprint/print.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/* -----------------------------------------------------------------------
-
-
- Blueprint CSS Framework 0.8
- http://blueprintcss.org
-
-   * Copyright (c) 2007-Present. See LICENSE for more info.
-   * See README for instructions on how to use Blueprint.
-   * For credits and origins, see AUTHORS.
-   * This is a compressed file. See the sources in the 'src' directory.
-
------------------------------------------------------------------------ */
-
-/* print.css */
-body {line-height:1.5;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;color:#000;background:none;font-size:10pt;}
-.container {background:none;}
-hr {background:#ccc;color:#ccc;width:100%;height:2px;margin:2em 0;padding:0;border:none;}
-hr.space {background:#fff;color:#fff;}
-h1, h2, h3, h4, h5, h6 {font-family:"Helvetica Neue", Arial, "Lucida Grande", sans-serif;}
-code {font:.9em "Courier New", Monaco, Courier, monospace;}
-img {float:left;margin:1.5em 1.5em 1.5em 0;}
-a img {border:none;}
-p img.top {margin-top:0;}
-blockquote {margin:1.5em;padding:1em;font-style:italic;font-size:.9em;}
-.small {font-size:.9em;}
-.large {font-size:1.1em;}
-.quiet {color:#999;}
-.hide {display:none;}
-a:link, a:visited {background:transparent;font-weight:700;text-decoration:underline;}
\ No newline at end of file
--- a/site-media/style/blueprint/screen.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,251 +0,0 @@
-/* -----------------------------------------------------------------------
-
-
- Blueprint CSS Framework 0.8
- http://blueprintcss.org
-
-   * Copyright (c) 2007-Present. See LICENSE for more info.
-   * See README for instructions on how to use Blueprint.
-   * For credits and origins, see AUTHORS.
-   * This is a compressed file. See the sources in the 'src' directory.
-
------------------------------------------------------------------------ */
-
-/* reset.css */
-html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;}
-body {line-height:1.5;}
-table {border-collapse:separate;border-spacing:0;}
-caption, th, td {text-align:left;font-weight:normal;}
-table, td, th {vertical-align:middle;}
-blockquote:before, blockquote:after, q:before, q:after {content:"";}
-blockquote, q {quotes:"" "";}
-a img {border:none;}
-
-/* typography.css */
-body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;}
-h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;}
-h1 {font-size:3em;line-height:1;margin-bottom:0.5em;}
-h2 {font-size:2em;margin-bottom:0.75em;}
-h3 {font-size:1.5em;line-height:1;margin-bottom:1em;}
-h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;}
-h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;}
-h6 {font-size:1em;font-weight:bold;}
-h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;}
-p {margin:0 0 1.5em;}
-p img.left {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;}
-p img.right {float:right;margin:1.5em 0 1.5em 1.5em;}
-a:focus, a:hover {color:#000;}
-a {color:#009;text-decoration:underline;}
-blockquote {margin:1.5em;color:#666;font-style:italic;}
-strong {font-weight:bold;}
-em, dfn {font-style:italic;}
-dfn {font-weight:bold;}
-sup, sub {line-height:0;}
-abbr, acronym {border-bottom:1px dotted #666;}
-address {margin:0 0 1.5em;font-style:italic;}
-del {color:#666;}
-pre {margin:1.5em 0;white-space:pre;}
-pre, code, tt {font:1em 'lucida console', monospace;line-height:1.5;}
-li ul, li ol {margin:0 1.5em;}
-ul, ol {margin:0 1.5em 1.5em 1.5em;}
-ul {list-style-type:disc;}
-ol {list-style-type:decimal;}
-dl {margin:0 0 1.5em 0;}
-dl dt {font-weight:bold;}
-dd {margin-left:1.5em;}
-table {margin-bottom:1.4em;width:100%;}
-th {font-weight:bold;}
-thead th {background:#c3d9ff;}
-th, td, caption {padding:4px 10px 4px 5px;}
-tr.even td {background:#e5ecf9;}
-tfoot {font-style:italic;}
-caption {background:#eee;}
-.small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;}
-.large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;}
-.hide {display:none;}
-.quiet {color:#666;}
-.loud {color:#000;}
-.highlight {background:#ff0;}
-.added {background:#060;color:#fff;}
-.removed {background:#900;color:#fff;}
-.first {margin-left:0;padding-left:0;}
-.last {margin-right:0;padding-right:0;}
-.top {margin-top:0;padding-top:0;}
-.bottom {margin-bottom:0;padding-bottom:0;}
-
-/* grid.css */
-.container {width:950px;margin:0 auto;}
-.showgrid {background:url(src/grid.png);}
-.column, div.span-1, div.span-2, div.span-3, div.span-4, div.span-5, div.span-6, div.span-7, div.span-8, div.span-9, div.span-10, div.span-11, div.span-12, div.span-13, div.span-14, div.span-15, div.span-16, div.span-17, div.span-18, div.span-19, div.span-20, div.span-21, div.span-22, div.span-23, div.span-24 {float:left;margin-right:10px;}
-.last, div.last {margin-right:0;}
-.span-1 {width:30px;}
-.span-2 {width:70px;}
-.span-3 {width:110px;}
-.span-4 {width:150px;}
-.span-5 {width:190px;}
-.span-6 {width:230px;}
-.span-7 {width:270px;}
-.span-8 {width:310px;}
-.span-9 {width:350px;}
-.span-10 {width:390px;}
-.span-11 {width:430px;}
-.span-12 {width:470px;}
-.span-13 {width:510px;}
-.span-14 {width:550px;}
-.span-15 {width:590px;}
-.span-16 {width:630px;}
-.span-17 {width:670px;}
-.span-18 {width:710px;}
-.span-19 {width:750px;}
-.span-20 {width:790px;}
-.span-21 {width:830px;}
-.span-22 {width:870px;}
-.span-23 {width:910px;}
-.span-24, div.span-24 {width:950px;margin:0;}
-input.span-1, textarea.span-1, select.span-1 {width:30px!important;}
-input.span-2, textarea.span-2, select.span-2 {width:50px!important;}
-input.span-3, textarea.span-3, select.span-3 {width:90px!important;}
-input.span-4, textarea.span-4, select.span-4 {width:130px!important;}
-input.span-5, textarea.span-5, select.span-5 {width:170px!important;}
-input.span-6, textarea.span-6, select.span-6 {width:210px!important;}
-input.span-7, textarea.span-7, select.span-7 {width:250px!important;}
-input.span-8, textarea.span-8, select.span-8 {width:290px!important;}
-input.span-9, textarea.span-9, select.span-9 {width:330px!important;}
-input.span-10, textarea.span-10, select.span-10 {width:370px!important;}
-input.span-11, textarea.span-11, select.span-11 {width:410px!important;}
-input.span-12, textarea.span-12, select.span-12 {width:450px!important;}
-input.span-13, textarea.span-13, select.span-13 {width:490px!important;}
-input.span-14, textarea.span-14, select.span-14 {width:530px!important;}
-input.span-15, textarea.span-15, select.span-15 {width:570px!important;}
-input.span-16, textarea.span-16, select.span-16 {width:610px!important;}
-input.span-17, textarea.span-17, select.span-17 {width:650px!important;}
-input.span-18, textarea.span-18, select.span-18 {width:690px!important;}
-input.span-19, textarea.span-19, select.span-19 {width:730px!important;}
-input.span-20, textarea.span-20, select.span-20 {width:770px!important;}
-input.span-21, textarea.span-21, select.span-21 {width:810px!important;}
-input.span-22, textarea.span-22, select.span-22 {width:850px!important;}
-input.span-23, textarea.span-23, select.span-23 {width:890px!important;}
-input.span-24, textarea.span-24, select.span-24 {width:940px!important;}
-.append-1 {padding-right:40px;}
-.append-2 {padding-right:80px;}
-.append-3 {padding-right:120px;}
-.append-4 {padding-right:160px;}
-.append-5 {padding-right:200px;}
-.append-6 {padding-right:240px;}
-.append-7 {padding-right:280px;}
-.append-8 {padding-right:320px;}
-.append-9 {padding-right:360px;}
-.append-10 {padding-right:400px;}
-.append-11 {padding-right:440px;}
-.append-12 {padding-right:480px;}
-.append-13 {padding-right:520px;}
-.append-14 {padding-right:560px;}
-.append-15 {padding-right:600px;}
-.append-16 {padding-right:640px;}
-.append-17 {padding-right:680px;}
-.append-18 {padding-right:720px;}
-.append-19 {padding-right:760px;}
-.append-20 {padding-right:800px;}
-.append-21 {padding-right:840px;}
-.append-22 {padding-right:880px;}
-.append-23 {padding-right:920px;}
-.prepend-1 {padding-left:40px;}
-.prepend-2 {padding-left:80px;}
-.prepend-3 {padding-left:120px;}
-.prepend-4 {padding-left:160px;}
-.prepend-5 {padding-left:200px;}
-.prepend-6 {padding-left:240px;}
-.prepend-7 {padding-left:280px;}
-.prepend-8 {padding-left:320px;}
-.prepend-9 {padding-left:360px;}
-.prepend-10 {padding-left:400px;}
-.prepend-11 {padding-left:440px;}
-.prepend-12 {padding-left:480px;}
-.prepend-13 {padding-left:520px;}
-.prepend-14 {padding-left:560px;}
-.prepend-15 {padding-left:600px;}
-.prepend-16 {padding-left:640px;}
-.prepend-17 {padding-left:680px;}
-.prepend-18 {padding-left:720px;}
-.prepend-19 {padding-left:760px;}
-.prepend-20 {padding-left:800px;}
-.prepend-21 {padding-left:840px;}
-.prepend-22 {padding-left:880px;}
-.prepend-23 {padding-left:920px;}
-div.border {padding-right:4px;margin-right:5px;border-right:1px solid #eee;}
-div.colborder {padding-right:24px;margin-right:25px;border-right:1px solid #eee;}
-.pull-1 {margin-left:-40px;}
-.pull-2 {margin-left:-80px;}
-.pull-3 {margin-left:-120px;}
-.pull-4 {margin-left:-160px;}
-.pull-5 {margin-left:-200px;}
-.pull-6 {margin-left:-240px;}
-.pull-7 {margin-left:-280px;}
-.pull-8 {margin-left:-320px;}
-.pull-9 {margin-left:-360px;}
-.pull-10 {margin-left:-400px;}
-.pull-11 {margin-left:-440px;}
-.pull-12 {margin-left:-480px;}
-.pull-13 {margin-left:-520px;}
-.pull-14 {margin-left:-560px;}
-.pull-15 {margin-left:-600px;}
-.pull-16 {margin-left:-640px;}
-.pull-17 {margin-left:-680px;}
-.pull-18 {margin-left:-720px;}
-.pull-19 {margin-left:-760px;}
-.pull-20 {margin-left:-800px;}
-.pull-21 {margin-left:-840px;}
-.pull-22 {margin-left:-880px;}
-.pull-23 {margin-left:-920px;}
-.pull-24 {margin-left:-960px;}
-.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float:left;position:relative;}
-.push-1 {margin:0 -40px 1.5em 40px;}
-.push-2 {margin:0 -80px 1.5em 80px;}
-.push-3 {margin:0 -120px 1.5em 120px;}
-.push-4 {margin:0 -160px 1.5em 160px;}
-.push-5 {margin:0 -200px 1.5em 200px;}
-.push-6 {margin:0 -240px 1.5em 240px;}
-.push-7 {margin:0 -280px 1.5em 280px;}
-.push-8 {margin:0 -320px 1.5em 320px;}
-.push-9 {margin:0 -360px 1.5em 360px;}
-.push-10 {margin:0 -400px 1.5em 400px;}
-.push-11 {margin:0 -440px 1.5em 440px;}
-.push-12 {margin:0 -480px 1.5em 480px;}
-.push-13 {margin:0 -520px 1.5em 520px;}
-.push-14 {margin:0 -560px 1.5em 560px;}
-.push-15 {margin:0 -600px 1.5em 600px;}
-.push-16 {margin:0 -640px 1.5em 640px;}
-.push-17 {margin:0 -680px 1.5em 680px;}
-.push-18 {margin:0 -720px 1.5em 720px;}
-.push-19 {margin:0 -760px 1.5em 760px;}
-.push-20 {margin:0 -800px 1.5em 800px;}
-.push-21 {margin:0 -840px 1.5em 840px;}
-.push-22 {margin:0 -880px 1.5em 880px;}
-.push-23 {margin:0 -920px 1.5em 920px;}
-.push-24 {margin:0 -960px 1.5em 960px;}
-.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float:right;position:relative;}
-.prepend-top {margin-top:1.5em;}
-.append-bottom {margin-bottom:1.5em;}
-.box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;}
-hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;}
-hr.space {background:#fff;color:#fff;}
-.clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;}
-.clearfix, .container {display:block;}
-.clear {clear:both;}
-
-/* forms.css */
-label {font-weight:bold;}
-fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;}
-legend {font-weight:bold;font-size:1.2em;}
-input.text, input.title, textarea, select {margin:0.5em 0;border:1px solid #bbb;}
-input.text:focus, input.title:focus, textarea:focus, select:focus {border:1px solid #666;}
-input.text, input.title {width:300px;padding:5px;}
-input.title {font-size:1.5em;}
-textarea {width:390px;height:250px;padding:5px;}
-.error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;}
-.error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;}
-.notice {background:#FFF6BF;color:#514721;border-color:#FFD324;}
-.success {background:#E6EFC2;color:#264409;border-color:#C6D880;}
-.error a {color:#8a1f11;}
-.notice a {color:#514721;}
-.success a {color:#264409;}
\ No newline at end of file
--- a/site-media/style/code.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/* @override http://localhost:8000/site-media/style/code.css */
-table.codehilitetable {
-    margin-left: 2em;
-}
-table.codehilitetable td {
-    border: none;
-    padding: 0;
-}
-table.codehilitetable td.linenos pre {
-    margin: 0em;
-    text-align: center;
-}
-table.codehilitetable td.code pre {
-    margin-right: 4em;
-}
-.codehilite .hll { background-color: #ffffcc }
-.codehilite .c { color: #8f5902; font-style: italic } /* Comment */
-.codehilite .err { color: #a40000; border: 1px solid #ef2929 } /* Error */
-.codehilite .g { color: #000000 } /* Generic */
-.codehilite .k { color: #204a87; font-weight: bold } /* Keyword */
-.codehilite .l { color: #000000 } /* Literal */
-.codehilite .n { color: #000000 } /* Name */
-.codehilite .o { color: #ce5c00; font-weight: bold } /* Operator */
-.codehilite .x { color: #000000 } /* Other */
-.codehilite .p { color: #000000; font-weight: bold } /* Punctuation */
-.codehilite .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */
-.codehilite .cp { color: #8f5902; font-style: italic } /* Comment.Preproc */
-.codehilite .c1 { color: #8f5902; font-style: italic } /* Comment.Single */
-.codehilite .cs { color: #8f5902; font-style: italic } /* Comment.Special */
-.codehilite .gd { color: #a40000 } /* Generic.Deleted */
-.codehilite .ge { color: #000000; font-style: italic } /* Generic.Emph */
-.codehilite .gr { color: #ef2929 } /* Generic.Error */
-.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
-.codehilite .gi { color: #00A000 } /* Generic.Inserted */
-.codehilite .go { color: #000000; font-style: italic } /* Generic.Output */
-.codehilite .gp { color: #8f5902 } /* Generic.Prompt */
-.codehilite .gs { color: #000000; font-weight: bold } /* Generic.Strong */
-.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
-.codehilite .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */
-.codehilite .kc { color: #204a87; font-weight: bold } /* Keyword.Constant */
-.codehilite .kd { color: #204a87; font-weight: bold } /* Keyword.Declaration */
-.codehilite .kn { color: #204a87; font-weight: bold } /* Keyword.Namespace */
-.codehilite .kp { color: #204a87; font-weight: bold } /* Keyword.Pseudo */
-.codehilite .kr { color: #204a87; font-weight: bold } /* Keyword.Reserved */
-.codehilite .kt { color: #204a87; font-weight: bold } /* Keyword.Type */
-.codehilite .ld { color: #000000 } /* Literal.Date */
-.codehilite .m { color: #0000cf; font-weight: bold } /* Literal.Number */
-.codehilite .s { color: #4e9a06 } /* Literal.String */
-.codehilite .na { color: #c4a000 } /* Name.Attribute */
-.codehilite .nb { color: #204a87 } /* Name.Builtin */
-.codehilite .nc { color: #000000 } /* Name.Class */
-.codehilite .no { color: #000000 } /* Name.Constant */
-.codehilite .nd { color: #5c35cc; font-weight: bold } /* Name.Decorator */
-.codehilite .ni { color: #ce5c00 } /* Name.Entity */
-.codehilite .ne { color: #cc0000; font-weight: bold } /* Name.Exception */
-.codehilite .nf { color: #000000 } /* Name.Function */
-.codehilite .nl { color: #f57900 } /* Name.Label */
-.codehilite .nn { color: #000000 } /* Name.Namespace */
-.codehilite .nx { color: #000000 } /* Name.Other */
-.codehilite .py { color: #000000 } /* Name.Property */
-.codehilite .nt { color: #204a87; font-weight: bold } /* Name.Tag */
-.codehilite .nv { color: #000000 } /* Name.Variable */
-.codehilite .ow { color: #204a87; font-weight: bold } /* Operator.Word */
-.codehilite .w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */
-.codehilite .mf { color: #0000cf; font-weight: bold } /* Literal.Number.Float */
-.codehilite .mh { color: #0000cf; font-weight: bold } /* Literal.Number.Hex */
-.codehilite .mi { color: #0000cf; font-weight: bold } /* Literal.Number.Integer */
-.codehilite .mo { color: #0000cf; font-weight: bold } /* Literal.Number.Oct */
-.codehilite .sb { color: #4e9a06 } /* Literal.String.Backtick */
-.codehilite .sc { color: #4e9a06 } /* Literal.String.Char */
-.codehilite .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */
-.codehilite .s2 { color: #4e9a06 } /* Literal.String.Double */
-.codehilite .se { color: #4e9a06 } /* Literal.String.Escape */
-.codehilite .sh { color: #4e9a06 } /* Literal.String.Heredoc */
-.codehilite .si { color: #4e9a06 } /* Literal.String.Interpol */
-.codehilite .sx { color: #4e9a06 } /* Literal.String.Other */
-.codehilite .sr { color: #4e9a06 } /* Literal.String.Regex */
-.codehilite .s1 { color: #4e9a06 } /* Literal.String.Single */
-.codehilite .ss { color: #4e9a06 } /* Literal.String.Symbol */
-.codehilite .bp { color: #3465a4 } /* Name.Builtin.Pseudo */
-.codehilite .vc { color: #000000 } /* Name.Variable.Class */
-.codehilite .vg { color: #000000 } /* Name.Variable.Global */
-.codehilite .vi { color: #000000 } /* Name.Variable.Instance */
-.codehilite .il { color: #0000cf; font-weight: bold } /* Literal.Number.Integer.Long */
\ No newline at end of file
--- a/site-media/style/comments.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-form#new-comment-form textarea {
-    width: 100%;
-}
\ No newline at end of file
--- a/site-media/style/gallery.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-div.gallery-pane { text-align: center; margin-bottom: 10px; }
-div.gallery img { padding: 0px; display: inline-block; border: 0px; }
--- a/site-media/style/messengerbag.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-div#mb-rendered-note h1 {font-size:2em;margin-bottom:0.75em;}
-div#mb-rendered-note h2 {font-size:1.5em;line-height:1;margin-bottom:1em;}
-div#mb-rendered-note h3 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;}
-div#mb-rendered-note h4 {font-size:1em;font-weight:bold;margin-bottom:1.5em;}
-div#mb-rendered-note h5 {font-size:1em;font-weight:bold;}
-div#mb-rendered-note h6 {font-size:1em;font-weight:bold;}
-
-p#mb-navigation { margin-top: -1em; }
-p#mb-navigation a { margin-right: 2em; }
-
-span.mb-note-list-title { font-weight: bold; margin-right: 1em; }
-span.mb-note-list-snip { color: #888; }
-
-form#mb-note-create h1 input { width: 81%; }
-form#mb-note-create p textarea { width: 80%; }
-input#mb-note-create-submit { font-size: 3em; }
--- a/site-media/style/photoblog.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-h1#photoblog-entry-title { margin-bottom: 0.1em;}
-div#photoblog-entry-date { color: #666; margin-top: 0em; margin-bottom: 2em; }
-
-img#photoblog-main-image { border: 10px solid #eee; margin: 1em auto 2em; display: block; }
-
-div.photoblog-nav-entry { border-bottom: 1px solid #eee; height: 54px; vertical-align: middle; }
-div.photoblog-nav-entry h2, div.photoblog-nav-entry h3 { line-height: 54px; display: inline; }
-div.photoblog-nav-entry img { float: right; margin: 2px 0px; }
-div#photoblog-nav-older { width: 48%; }
-div#photoblog-nav-newer { width: 48%; float: right; }
\ No newline at end of file
--- a/site-media/style/print.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-/* @override http://localhost:8000/site-media/style/print.css */
-
-div#sidebar {
-    display: none;
-}
-div#blog-entry-new-comment {
-    display:  none;
-}
-div#projects-project-new-comment {
-    display:  none;
-}
-div#header {
-   font-size: 0.75em; 
-}
-ul.print-links {
-    display: block;
-    font-size: 1em;
-    list-style-type: none;
-    font-style: italic;
-    margin-left: 0em;
-}
\ No newline at end of file
--- a/site-media/style/projects.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/* @override http://127.0.0.1:8000/site-media/style/projects.css */
-div.projects-list-entry {
-    border-bottom: 1px solid #eee;
-    height: 3em;
-    line-height: 3em;
-    -webkit-text-size-adjust: none;
-}
-h2.projects-list-entry-title {
-    display: inline;
-}
-p.projects-list-entry-snip {
-    display: inline;
-    padding-left: 1em;
-    color: #666;
-}
-div#projects-project-date {
-    color: #666;
-}
-div.projects-project-comment-body {
-    margin-left: 2em;
-}
-div.wmd-preview {
-    margin-left: 2em;
-}
-div.projects-project-comment-body h1, .wmd-preview h1 {
-    font-size: 1.4em;
-}
-div.projects-project-comment-body h2, .wmd-preview h2 {
-    font-size: 1.3em;
-}
-div.projects-project-comment-body pre {
-    font-size: 1em;
-    line-height: 1.5em;
-}
-div.projects-project-comment-body h3, .wmd-preview h3, div.projects-project-comment-body h4, .wmd-preview h4, div.projects-project-comment-body h5, .wmd-preview h5, div.projects-project-comment-body h6, .wmd-preview h6 {
-    font-size: 1.2em;
-}
-input#projects-new-comment-name {
-    width: 40%;
-    margin-right: 1em;
-}
-input#projects-new-comment-submit {
-    margin-top: 1.5em;
-}
-p#projects-new-comment-body-area {
-    margin-bottom: 0em;
-}
-p#projects-new-comment-instructions {
-    margin-top: 0em;
-}
-span#projects-new-comment-invalid-body {
-    float: right;
-}
-#projects-new-comment-name-area label.invalid {
-    display: inline;
-}
-#projects-new-comment-body-area label.invalid {
-    float: right;
-}
-.content img {
-    text-align: left;
-    margin-right: auto;
-    margin-left: auto;
-    border: 10px solid #eee;
-    display: block;
-    padding: 1px;
-    background-color: #000;
-}
\ No newline at end of file
--- a/site-media/style/splash.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-div.splash-list-entry {
-    border-bottom: 1px solid #eee;
-    height: 3em;
-    text-align: right;
-}
-
-#splash-list h2 {
-    display: inline;
-    color: #666;
-    font-weight: normal;
-    font-size: 1.5em;
-    line-height: 2em;
-    -webkit-text-size-adjust: none;
-    margin: 0em;
-}
\ No newline at end of file
--- a/site-media/style/stevelosh.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/* @override http://stevelosh.com/site-media/style/stevelosh.css */
-
-body.stevelosh {
-    color: #111;
-}
-div#wrapper {
-    margin-bottom: 5em;
-}
-p code, li code {
-    background-color: #eee; padding: 2px; border: 1px solid #ddd;
-}
-input, textarea {
-    font-size: 1.0em;
-    margin: 0em;
-}
-ol, ul {
-    padding-left: 2em;
-}
-pre, blockquote {
-    margin-left: 2em;
-    margin-right: 2em;
-    background-color: #f5f5f5;
-    padding: 1.5em;
-    border: 1px solid #ddd;
-}
-a:link, a:visited, a:active {
-    color: #e50053;
-    text-decoration: none;
-}
-a:hover {
-    text-decoration: underline;
-}
-#wrapper {
-    border: 1px solid white;
-}
-div#header {
-    margin-bottom: 3em;
-}
-div#header h1 {
-    font-size: 6em;
-    line-height: 1em;
-    display: inline;
-    font-weight: normal;
-    letter-spacing: -4px;
-}
-h1#site-logo {
-    color: black;
-}
-h1#site-heading {
-    color: #666;
-}
-h1 a:link, h1 a:visited, h1 a:active, h2 a:link, h2 a:visited, h2 a:active,
-h3 a:link, h3 a:visited, h3 a:active {
-    color: black;
-    text-decoration: none;
-}
-h1 a:hover, h2 a:hover, h3 a:hover {
-    color: #e50053;
-}
-div#sidebar div.sidebar-item {
-    border-bottom: 1px solid #eee;
-    height: 3em;
-}
-div#sidebar h2 {
-    display: inline;
-    font-size: 1.5em;
-    line-height: 2em;
-    margin-bottom: 0em;
-    -webkit-text-size-adjust: none;
-}
-ul.print-links {
-    display: none;
-}
-p.form-label {
-    color: #666;
-    margin-bottom: 0em;
-}
-label.invalid {
-    font-size: 1em;
-    font-weight: normal;
-}
-.invalid {
-    color: #F00;
-}
-
-div.toc ul {
-    list-style-type: none;
-    padding-left: 0;
-}
-div.toc > ul > li {
-    margin-left: 0;
-}
-
-/* Typogrify Styles */
-
-.amp { 
-	color: #444;
-	font: italic 1.05em "Hoefler Text", "Warnock Pro", Palatino, "Book Antiqua", serif;
-	font-weight: inherit;
-}
-a .amp { color: inherit; }
-a:hover .amp { color: inherit; }
-.caps { font-size: 0.92em; font-weight: inherit;}
-.quo { margin-left: -0.30em; }
-.dquo { margin-left: -0.38em; }
-img.inline-photo-right {
-    float: right;
-    margin-left: 1.5em;
-}
-img.inline-photo-left {
-    float: left;
-    margin-right: 1.5em;
-}
\ No newline at end of file
--- a/site-media/style/thoughts.css	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-div.thought-content {
-    border-bottom: 1px solid #eee;
-    margin-bottom: 3.5em;
-}
-
-div.thought p:last-child {
-    margin-bottom: 1em;
-}
-
-.thought h2 {
-    display: inline;
-    font-size: 1.5em;
-}
-
-div.thought-content h2 {
-    display: block;
-    margin-bottom: 0.5em;
-}
-
-.thought h2 a:link, .thought h2 a:visited, .thought h2 a:active {
-    border-bottom: 1px dotted #666;
-}
-
-.thought h2 a:hover {
-    border-bottom: 1px dotted #900;
-}
-
-.thought-type {
-    text-align: right;
-}
-
-.thought-type h2 {
-    color: #666;
-    font-weight: normal;
-}
-
-.colborder-left {
-    padding-left: 25px;
-    margin-left: 14px;
-    border-left: 1px solid #eee;
-}
-
-span#thought-list-newer {
-    float: right;
-}
\ No newline at end of file
--- a/templates/404.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}Not Found{% endblock %}
-
-{% block header %}/ not found{% endblock %}
-
-{% block content %}
-	<h1>Not Found</h1>
-	<p>Sorry, we couldn't find whatever you're looking for.</p>
-	<p>If you followed a bookmark or link here, it might be out of date because I recently redesigned the site.  Check the links on the right to find what you're looking for.</p>
-	<p>If you still can't find it, <a href="mailto:steve@stevelosh.com">email me</a>.</p>
-{% endblock %}
\ No newline at end of file
--- a/templates/base.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-    <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
-    <title>{% block title %}{% endblock %} / Steve Losh</title>
-    
-    <link rel="stylesheet" href="/site-media/style/blueprint/screen.css" 
-          type="text/css" media="screen, projection"/>
-    <link rel="stylesheet" href="/site-media/style/blueprint/print.css" 
-          type="text/css" media="print"/> 
-    <!--[if IE]>
-    <link rel="stylesheet" href="/site-media/style/blueprint/ie.css"
-          type="text/css" media="screen, projection">
-    <![endif]-->
-    <link rel="stylesheet" href="/site-media/style/aal.css" 
-          type="text/css" media="screen, projection"/>
-    <link rel="stylesheet" href="/site-media/style/stevelosh.css" 
-          type="text/css"/>
-    <link rel="stylesheet" href="/site-media/style/comments.css" 
-          type="text/css"/>
-        
-    {% block style %}{% endblock %}
-    
-    <link rel="stylesheet" href="/site-media/style/print.css" 
-          type="text/css" media="print"/> 
-    
-    <script type="text/javascript"
-            src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js">
-    </script>
-    <script src="/mint/?js" type="text/javascript"></script>
-    
-    <script type="text/javascript"
-            src="/site-media/scripts/print-links.js">
-    </script>
-    
-    {% block script %}{% endblock %}
-    
-    <link rel="alternate" type="application/rss+xml" 
-          title="RSS Feed for stevelosh.com" 
-          href="http://feeds2.feedburner.com/stevelosh" />
-</head>
-
-<body class="stevelosh">
-    <div id="wrapper" class="container">
-        <div id="header" class="span-24">
-            <h1 id="site-logo"><a href="/">steve losh</a></h1>
-            <h1 id="site-heading">
-                &nbsp;{% block header %}{% endblock %}
-            </h1>
-        </div>
-        
-        <div id="content" class="span-17 colborder">
-            {% block content %}{% endblock %}
-        </div>
-        
-        <div id="sidebar" class="span-6 last">
-            <div class="sidebar-item">
-                <h2><a href="{% url blog-list-newest %}">
-                    Blog
-                </a></h2>
-            </div>
-            
-            <div class="sidebar-item">
-                <h2><a href="http://bitbucket.org/sjl/">
-                    Source
-                </a></h2>
-            </div>
-            
-            <div class="sidebar-item">
-                <h2><a href="{% url project-list %}">
-                    Projects
-                </a></h2>
-            </div>
-            
-            <div class="sidebar-item">
-                <h2><a href="/about/">
-                    About
-                </a></h2>
-            </div>
-            
-            <div class="sidebar-item">
-                <h2><a href="http://feeds2.feedburner.com/stevelosh">
-                    RSS
-                </a></h2>
-            </div>
-        </div>
-    </div>
-</body>
-
-</html>
\ No newline at end of file
--- a/templates/blog/base.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}Blog{% endblock %}
-
-{% block style %}
-	<link rel="stylesheet" href="/site-media/style/blog.css" 
-		  type="text/css"/>
-	<link rel="stylesheet" href="/site-media/style/code.css" 
-		  type="text/css"/>
-{% endblock %}
-
-{% block header %}/ blog{% endblock %}
\ No newline at end of file
--- a/templates/blog/entry.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-{% extends "blog/base.html" %}
-{% load markup %}
-{% load typogrify %}
-
-{% block title %}{{ entry.title }}{% endblock %}
-
-{% block script %}
-    <script type="text/javascript"
-            src="/site-media/scripts/jquery.validate.min.js">
-    </script>
-    <script type="text/javascript"
-            src="/site-media/scripts/validate-comment-form.js">
-    </script>
-{% endblock %}
-
-{% block content %}
-    <div id="blog-entry">
-        <h1 id="blog-entry-title">
-            <a href="{{ entry.get_absolute_url }}">
-                {{ entry.title|typogrify }}
-            </a>
-        </h1>
-        <div id="blog-entry-date">
-            <p>
-                Posted
-                on {{ entry.pub_date.date|date:"F j, Y" }}
-                at {{ entry.pub_date.time|time:"g:i A" }}
-            </p>
-        </div>
-        <div id="blog-entry-body" class="content">
-            {{ entry.body|markdown:"codehilite,toc"|typogrify }}
-        </div>
-    </div>
-    <hr />
-    {% ifnotequal comments.count 0 %}
-        <div id="blog-entry-comments">
-            <h1>Comments</h1>
-            {% for comment in comments %}
-                <div class="blog-entry-comment">
-                    <a name="comment-{{ comment.id }}"></a>
-                    <h2>{{ comment.name }} said:</h2>
-                    <div class="blog-entry-comment-body">
-                        {{ comment.body|markdown:"safe"|typogrify }}
-                    </div>
-                </div>
-            {% endfor %}
-        </div>
-        <hr />
-    {% endifnotequal %}
-    <div id="blog-entry-new-comment">
-        <h1>Add your comment:</h1>
-        <form id="new-comment-form" method="post" 
-              action="{% url blog-post-comment %}">
-            <p class="form-label">
-                What's your name?
-            </p>
-            <p id="blog-new-comment-name-area">
-                <input type="hidden" name="entry-id" 
-                       value="{{ entry.id }}" />
-                <input id="blog-new-comment-name" name="name" 
-                       maxlength="40" type="text" />
-            </p>
-            <p id="blog-new-comment-body-area">
-                <textarea id="blog-new-comment-body" rows="" cols=""
-                          name="body"></textarea>
-            </p>
-            <p id="blog-new-comment-instructions">
-                You can use <a href="http://daringfireball.net/projects/markdown/syntax">Markdown</a>.
-            </p>
-            <h2>You're going to say:</h2>
-            <div class="wmd-preview"></div>
-            <p>
-                <input id="blog-new-comment-submit" name="submit"
-                       type="submit" value="Comment" />
-            </p>
-        </form>
-    </div>
-    
-    <script type="text/javascript">
-        wmd_options = {
-            output: "Markdown",
-            buttons: "bold italic | link blockquote code | ol ul heading hr"
-        };
-    </script>
-    <script type="text/javascript"
-            src="/site-media/scripts/wmd/wmd.js"></script>
-    
-{% endblock %}
\ No newline at end of file
--- a/templates/blog/list.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-{% extends "blog/base.html" %}
-{% load typogrify %}
-
-{% block content %}
-    <div id="blog-list">
-        {% for entry in entries %}
-            <div class="blog-list-entry">
-                <h2 class="blog-list-entry-title">
-                    <a href="{{ entry.get_absolute_url }}">
-                        {{ entry.title|typogrify }}
-                    </a>
-                </h2>
-                <p class="blog-list-entry-snip">{{ entry.snip|typogrify }}</p>
-            </div>
-        {% endfor %}
-        
-        {% ifnotequal newer_page older_page  %}
-            <div id="blog-list-nav" class="blog-list-entry">
-            {% ifnotequal newer_page None %}
-                {% ifequal newer_page 0 %}
-                    {% url blog-list-newest as new_page %}
-                {% else %}
-                    {% url blog-list-page newer_page as new_page %}
-                {% endifequal %}
-                
-                <h2 id="blog-list-newer"><a href="{{ new_page }}">
-                    Newer &raquo;
-                </a></h2>
-            {% endifnotequal %}
-            {% ifnotequal older_page None %}
-                <h2 id="blog-list-older">
-                    <a href="{% url blog-list-page older_page %}">
-                        &laquo; Older
-                    </a>
-                </h2>
-            {% else %}
-                <h2 id="blog-list-older">&nbsp;</h2>
-            {% endifnotequal %}
-            </div>
-        {% endifnotequal %}
-    </div>
-{% endblock %}
\ No newline at end of file
--- a/templates/feeds/all_description.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-{% load markup %}
-
-{{ obj.item.body|markdown }}
\ No newline at end of file
--- a/templates/feeds/all_title.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-{{ obj.title }}
\ No newline at end of file
--- a/templates/feeds/comments_description.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-{% load markup %}{{ obj.body|markdown:"safe" }}
\ No newline at end of file
--- a/templates/feeds/comments_title.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Comment on {% if obj.entry.title %}{{ obj.entry.title }}{% else %}{{ obj.project.name }}{% endif %} by {{ obj.name }}
\ No newline at end of file
--- a/templates/flatpages/default.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-{% extends "base.html" %}
-{% load markup %}
-{% load typogrify %}
-
-{% block title %}{{ flatpage.title }}{% endblock %}
-
-{% block header %}/ {{ flatpage.title|lower }}{% endblock %}
-
-{% block content %}
-	<div id="flatpage-content">
-		{{ flatpage.content|markdown|typogrify }}
-	</div>
-{% endblock %}
\ No newline at end of file
--- a/templates/flatpages/splash.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-{% extends "flatpages/default.html" %}
-{% load typogrify %}
-
-{% block style %}
-    <link rel="stylesheet" href="/site-media/style/splash.css" 
-          type="text/css"/>
-{% endblock %}
-
-{% block content %}
-{% filter typogrify %}
-    <div id="splash-list">
-        <div class="splash-list-entry">
-            <h2>I like writing. &raquo;</h2>
-        </div>
-        <div class="splash-list-entry">
-            <h2>What makes me tick. &raquo;</h2>
-        </div>
-        <div class="splash-list-entry">
-            <h2>Some things I've made. &raquo;</h2>
-        </div>
-        <div class="splash-list-entry">
-            <h2>More about me. &raquo;</h2>
-        </div>
-        <div class="splash-list-entry">
-            <h2>Tasty feeds. &raquo;</h2>
-        </div>
-    </div>
-{% endfilter %}
-{% endblock %}
\ No newline at end of file
--- a/templates/messengerbag/base.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}Messenger Bag{% endblock %}
-{% block header %}/ messenger bag{% endblock %}
-
-{% block style %}
-    <link rel="stylesheet" href="/site-media/style/messengerbag.css" 
-          type="text/css"/>
-{% endblock %}
--- a/templates/messengerbag/note_detail.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-{% extends "messengerbag/base.html" %}
-{% load typogrify %}
-{% load markup %}
-
-{% block title %}{{ note.title }}{% endblock %}
-
-{% block content %}
-    <h1><a href="{{ note.get_absolute_url }}">{{ note.title|typogrify }}</a></h1>
-    <p id="mb-navigation">
-        <a href="{% url note-list %}">&laquo; back to your notes</a>
-        <a href="{% url note-edit note.id %}">edit this note</a>
-    </p>
-    <div id="mb-rendered-note">
-        {{ note.body|markdown:"codehilite"|typogrify }}
-    </div>
-{% endblock %}
\ No newline at end of file
--- a/templates/messengerbag/note_form.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-{% extends "messengerbag/base.html" %}
-{% load typogrify %}
-{% load markup %}
-
-{% block title %}Create a Note{% endblock %}
-
-{% block content %}
-    
-    <form id="mb-note-create" action="" method="post">
-        <h1>{{ form.title }}</h1>
-        {% for error in form.title.errors %}
-            <p class="mb-error">{{ error }}</p>
-        {% endfor %}
-        
-        <p id="mb-navigation">
-            <a href="{% url note-list %}">&laquo; back to your notes</a>
-        </p>
-        
-        <p>{{ form.body }}</p>
-        {% for error in form.body.errors %}
-            <p class="mb-error">{{ error }}</p>
-        {% endfor %}
-        
-        <input id="mb-note-create-submit" type="submit" value="Save" />
-    </form>
-{% endblock %}
\ No newline at end of file
--- a/templates/messengerbag/note_list.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-{% extends "messengerbag/base.html" %}
-{% load typogrify %}
-
-{% block title %}Messenger Bag{% endblock %}
-
-{% block content %}
-    <h1>Notebook</h1>
-    <p id="mb-navigation">
-        <a href="{% url note-create %}">+ Create a new note</a>
-    </p>
-    <p id="mb-note-list">
-        {% for note in note_list %}
-            <span class="mb-note-list-title">
-                <a href="{{ note.get_absolute_url }}">{{ note.title|typogrify }}</a>
-            </span>
-            <span class="mb-note-list-snip">{{ note.snippet|typogrify }}</span>
-            <br/>
-        {% endfor %}
-    </p>
-{% endblock %}
\ No newline at end of file
--- a/templates/projects/base.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-{% extends "base.html" %}
-
-{% block title %}Projects{% endblock %}
-
-{% block style %}
-	<link rel="stylesheet" href="/site-media/style/projects.css" 
-		  type="text/css"/>
-	<link rel="stylesheet" href="/site-media/style/gallery.css" 
-		  type="text/css"/>
-	<link rel="stylesheet" href="/site-media/style/code.css" 
-		  type="text/css"/>
-{% endblock %}
-
-{% block header %}/ projects{% endblock %}
\ No newline at end of file
--- a/templates/projects/list.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-{% extends "projects/base.html" %}
-{% load typogrify %}
-
-{% block content %}
-    <div id="projects-list">
-        <div class="projects-list-entry">
-            <h2 class="projects-list-entry-title">Programming</h2>
-            <p class="projects-list-entry-snip">&nbsp;</p>
-        </div>
-        {% for project in programming %}
-            <div class="projects-list-entry">
-                <h2 class="projects-list-entry-title">
-                    <a href="{{ project.get_absolute_url }}">
-                        {{ project.name|typogrify }}
-                    </a>
-                </h2>
-                <p class="projects-list-entry-snip">{{ project.snip|typogrify }}</p>
-            </div>
-        {% endfor %}
-        
-        <div class="projects-list-entry">
-            <h2 class="projects-list-entry-title">&nbsp;</h2>
-            <p class="projects-list-entry-snip">&nbsp;</p>
-        </div>
-        
-        <div class="projects-list-entry">
-            <h2 class="projects-list-entry-title">Photography</h2>
-            <p class="projects-list-entry-snip">&nbsp;</p>
-        </div>
-        {% for project in photo %}
-            <div class="projects-list-entry">
-                <h2 class="projects-list-entry-title">
-                    <a href="{{ project.get_absolute_url }}">
-                        {{ project.name|typogrify }}
-                    </a>
-                </h2>
-                <p class="projects-list-entry-snip">{{ project.snip|typogrify }}</p>
-            </div>
-        {% endfor %}
-    </div>
-{% endblock %}
\ No newline at end of file
--- a/templates/projects/project.html	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-{% extends "projects/base.html" %}
-{% load markup %}
-{% load typogrify %}
-
-{% block title %}{{ project.name }}{% endblock %}
-
-{% block script %}
-    <script type="text/javascript"
-            src="/site-media/scripts/jquery.validate.min.js">
-    </script>
-    <script type="text/javascript"
-            src="/site-media/scripts/validate-comment-form.js">
-    </script>
-    <script type="text/javascript"
-            src="/site-media/scripts/stevelosh-gallery.js">
-    </script>
-{% endblock %}
-
-{% block content %}
-    <div id="projects-project">
-        <h1 id="projects-project-name">
-            <a href="{{ project.get_absolute_url }}">
-                    {{ project.name|typogrify }}
-            </a>
-        </h1>
-        <div id="projects-project-date">
-            <p>
-                Posted
-                on {{ project.posted.date|date:"F j, Y" }}
-                at {{ project.posted.time|time:"g:i A" }}
-            </p>
-        </div>
-        <div id="projects-project-body" class="content">
-            {{ project.body|markdown:"codehilite,toc"|typogrify }}
-        </div>
-    </div>
-    <hr />
-    {% ifnotequal comments.count 0 %}
-        <div id="projects-project-comments">
-            <h1>Comments</h1>
-            {% for comment in comments %}
-                <div class="projects-project-comment">
-                    <a name="comment-{{ comment.id }}"></a>
-                    <h2>{{ comment.name }} said:</h2>
-                    <div class="projects-project-comment-body">
-                        {{ comment.body|markdown:"safe"|typogrify }}
-                    </div>
-                </div>
-            {% endfor %}
-        </div>
-        <hr />
-    {% endifnotequal %}
-    <div id="projects-project-new-comment">
-        <h1>Add your comment:</h1>
-        <form id="new-comment-form" method="post" 
-              action="{% url project-post-comment %}">
-            <p class="form-label">
-                What's your name?
-            </p>
-            <p id="projects-new-comment-name-area">
-                <input type="hidden" name="project-id" 
-                       value="{{ project.id }}" />
-                <input id="projects-new-comment-name" name="name" 
-                       maxlength="40" type="text" />
-            </p>
-            <p id="projects-new-comment-body-area">
-                <textarea id="projects-new-comment-body" rows="" cols=""
-                          name="body"></textarea>
-            </p>
-            <p id="projects-new-comment-instructions">
-                You can use <a href="http://daringfireball.net/projects/markdown/syntax">Markdown</a>.
-            </p>
-            <h2>You're going to say:</h2>
-            <div class="wmd-preview"></div>
-            <p>
-                <input id="projects-new-comment-submit" name="submit"
-                       type="submit" value="Comment" />
-            </p>
-        </form>
-    </div>
-    
-    <script type="text/javascript">
-        wmd_options = {
-            output: "Markdown",
-            buttons: "bold italic | link blockquote code | ol ul heading hr"
-        };
-    </script>
-    <script type="text/javascript"
-            src="/site-media/scripts/wmd/wmd.js"></script>
-    
-{% endblock %}
\ No newline at end of file
--- a/urls.py	Sat Jan 09 03:42:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-from django.conf.urls.defaults import *
-from django.contrib import admin
-from django.conf import settings
-import mobileadmin
-
-admin.autodiscover()
-mobileadmin.autoregister()
-
-urlpatterns = patterns('',
-    (r'^admin/(.*)', admin.site.root),
-    (r'^m/(.*)', mobileadmin.sites.site.root),
-    url(r'^blog/', include('stevelosh.blog.urls')),
-    url(r'^projects/', include('stevelosh.projects.urls')),
-    url(r'^rss/', include('stevelosh.rss.urls')),
-    url(r'^mb/', include('stevelosh.messengerbag.urls')),
-
-)
-
-if settings.DEBUG:
-    urlpatterns += patterns('',
-        (r'^site-media/(?P<path>.*)$', 'django.views.static.serve',
-         {'document_root': settings.MEDIA_ROOT}),
-    )
-
-handler404 = 'mobileadmin.views.page_not_found'
-handler500 = 'mobileadmin.views.server_error'