Hacking on Octopress

Posted on Mon 11 February 2013 in Dispatches • 5 min read

As previously discussed, I recently switched to Octopress on this site. I’ve been pretty happy with that decision thus far. Performance is good thanks to static files. It’s a joy to compose in Markdown, preview it on my own machine, and then deploy to my site. Plus, since the whole site lives in a Git repository, I can easily branch to try things out, whether it be structural or content-based changes.

However, as I’ve been working with it, I’ve found a few opportunities to modify the code in order to help improve my workflow.

Draft By Default

Octopress works from the assumption that when you create a new post or page that it should be considered published by default. This is exactly the opposite of what I want it to do. I often work with multiple drafts at a time and it would be easy to accidentally deploy a post that was not ready. You can, of course, use the published: false variable at the top of the file, but I’m more comfortable changing that when I’m ready to publish rather than remembering to do that every time I initially create a file. So, I added an option to specify a default mode for post/page creation.

The diff for that looks like this:

diff --git a/Rakefile b/Rakefile
index 471b227..1121384 100644
--- a/Rakefile
+++ b/Rakefile
@@ -26,6 +26,7 @@ themes_dir      = ".themes"   # directory for blog files
new_post_ext    = "markdown"  # default new post file extension when using the new_post task
new_page_ext    = "markdown"  # default new page file extension when using the new_page task
server_port     = "4000"      # port for preview server eg. localhost:4000
+publish_default = "false"     # default published status for new posts and pages


desc "Initial setup for Octopress: copies the default theme into the path of Jekyll's generator. Rake install defaults to rake install[classic] to install a different theme run rake install[some_theme_name]"
@@ -110,6 +111,7 @@ task :new_post, :title do |t, args|
    post.puts "title: \"#{title.gsub(/&/,'&')}\""
    post.puts "date: #{Time.now.strftime('%Y-%m-%d %H:%M')}"
    post.puts "comments: true"
+    post.puts "published: #{publish_default}"
    post.puts "categories: "
    post.puts "---"
end
@@ -147,6 +149,7 @@ task :new_page, :filename do |t, args|
    page.puts "comments: true"
    page.puts "sharing: true"
    page.puts "footer: true"
+      page.puts "published: #{publish_default}"
    page.puts "---"
    end
else

Now, whenever I create a new post, it sets it to a draft mode by default, and it will only be deployed if I explicitly change it to published: true after I am done writing it. It works well for me and I have already submitted a pull request for it.

Quick Quote Posting

I love collecting quotes, and love to share them with others. Oddly, I’ve never done that much on this site, with the exception of link posts. There’s honestly not a lot of difference between a normal post and a quote post structurally, but I wanted a short cut so that I could create quick and short entries based around a single blockquote.

To do this, I added a Rake task to my installation.

desc "Begin a new quote in #{source_dir}/#{posts_dir}"
task :new_quote, :title do |t, args|
if args.title
    title = "Quote: #{args.title}"
else
    title = get_stdin("Enter a title for your quote: ")
end
raise "### You haven't set anything up yet. First run `rake install` to set up an Octopress theme." unless File.directory?(source_dir)
mkdir_p "#{source_dir}/#{posts_dir}"
filename = "#{source_dir}/#{posts_dir}/#{Time.now.strftime('%Y-%m-%d')}-#{title.to_url}.#{new_post_ext}"
if File.exist?(filename)
    abort("rake aborted!") if ask("#{filename} already exists. Do you want to overwrite?", ['y', 'n']) == 'n'
end
puts "Creating new post: #{filename}"
open(filename, 'w') do |post|
    post.puts "---"
    post.puts "layout: post"
    post.puts "title: \"#{title.gsub(/&/,'&')}\""
    post.puts "date: #{Time.now.strftime('%Y-%m-%d %H:%M')}"
    post.puts "comments: true"
    post.puts "is_quote: true"
    post.puts "published: #{publish_default}"
    post.puts "categories: "
    post.puts "- quote"
    post.puts "---"
    post.puts "{% raw %}{% blockquote #{args.title} [link] %}{% endraw %}"
    post.puts ""
    post.puts "{% raw %}{% endblockquote %}{% endraw %}"
end
end

This sets me up with a nice template for filling in my quote post. Running a command like rake new_quote['Richard Stallman'], gives me the file below.

---
layout: post
title: "Quote: Richard Stallman"
date: 2013-02-11 22:07
comments: true
is_quote: true
published: false
categories:
- quote
{% blockquote Richard Stallman [link] %}

{% endblockquote %}

I can paste in the quote, optionally paste in a link to the source, and then preview it before publishing. It’s a small convenience, but I like it.

I’ve been meaning to switch around the ordering of urls for my link posts for quite some time. If I’m posting a link to another site, and really only adding a sentence of commentary, the most important link is the external one.

This one required almost no creativity on my part as it’s already laid out quite well by Jonathan Poritsky in this blog post. I’ve essentially done the same thing he describes there. Now, all my link posts on this site link initially to the source material, but also provide a permalink to my post using the ‘∞’ character. To keep them easy to recognize, all link titles are prefixed with ‘♺’.

The archive lists and RSS feed don’t replicate this behavior, because honestly it’s less clear in a feed reader what to expect, so being taken to the source site instead of the originating post is frustrating for me as a reader. Even though I know it’s the behavior for some of my regular reads, I almost always forget on the first entry and have to hit the back button. In the case of my RSS feed, I automatically add a “Link to Source” anchor to explicitly identify the source material.

Avoiding Tentacle Horror

The best part of these changes is that they were all relatively easy to implement. The Liquid templates are similar enough to the Django template syntax that the changes were self-explanatory, even if the parser is a little easily confused. The Ruby was pretty straightforward as well. The challenge with any publishing tool that encourages hacking is the temptation to fiddle with it as opposed to actually writing. It doesn’t take much tinkering in any piece of software before you find yourself being dragged beneath the waves towards its hideous beak.

I’m happy to say that the changes above have been pretty minimal, especially compared to my other experiences with CMS software, where I would often spend days looking through plugin directories and source code. I’m not sure if that speaks more to the polish of Octopress, or more to my approach to software these days, but regardless I’m still enjoying using it. More importantly, I’m actually writing here again, and that was the point all along.