In the process of moving this blog from Typo to Webby, it quickly became obvious that copying the blog posts over by hand was not an option. Searching on Google led me to a task for importing the posts using an RSS feed, but since I used an SQLite3 database with Typo, I thought it would be easier to just grab the posts directly from the database file.
The bulk of the changes are in this changelist on GitHub, but I made a few more modifications to the process that are included in later changelists.
tasks/blog.rake differs mainly in that it uses the actual database instead of an RSS feed and has regular expressions to convert my Typo code highlighting to use Webby’s UltraVioletHelper. The code is also cleaned up a bit, to use Rake arguments instead of passing around the created_at time as an ENV variable and also to avoid copying Webby::Apps::Main#capture_command_line_args. Changing the database source is left as an exercise for the reader.
desc "Import blog posts" task :import_posts, :dbfile do |t,args| require 'active_record' ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :dbfile => args.dbfile ) class Content < ActiveRecord::Base; end class Page < Content; end class Article < Content; end Article.find(:all, :conditions => { :published => true }).each do |post| published_at = post.published_at page = ::Webby::Resources.basename(post.title).to_url title = post.title dir = "#{Webby.site.blog_dir}/#{published_at.strftime('%Y/%m/%d')}" ::Webby.site.args = OpenStruct.new(:raw => [title], :page => page, :title => title, :dir => '') year = published_at.strftime('%Y') month = published_at.strftime('%m') Rake::Task['blog:create_year_index'].execute(Rake::TaskArguments.new([:year], [year])) Rake::Task['blog:create_month_index'].execute(Rake::TaskArguments.new([:year, :month], [year, month])) page = File.join(dir, File.basename(page)) # Colons in the title isn't correct YAML title = "\"#{title}\"" if title =~ /:/ body = post.body # Convert the Ultraviolet textfilter blocks body.gsub!(/<typo:ultraviolet(.*?)>/, '<% uv\1 do -%>') body.gsub!('</typo:ultraviolet>', '<% end -%>') body.gsub!(/<% uv (.*) do -%>/) do s = $1.split(' ').map {|i| i.gsub(/(.*)="(.*)"/) { ":#$1 => '#$2'" }}.join(', ') s.sub!('linenumber', 'line_numbers') "<% uv #{s} do -%>" end # Remove extra carriage returns from the SQLite3 string. body.gsub!("\r", '') Webby::Builder.create(page, :from => File.join(Webby.site.template_dir, 'blog', 'post.erb'), :locals => { :title => title, :directory => dir, :body => body, :created_at => published_at.to_y }) end end
You’ll have to of course add the <%= body %> tag in post.erb.
Adding arguments to the year and month indices isn’t too complicated. At the same time, I disabled the dirty flag for the indices created by the imported posts, as they don’t need to be re-rendered more than once.
task :create_year_index, :year do |t,args| args.with_defaults(:year => Time.now.strftime('%Y')) year = args.year ... snip ... Webby::Builder.create(fn, :from => tmpl, :locals => {:title => year, :directory => dir, :dirty => (year == Time.now.strftime('%Y'))}) end end
task :create_month_index, :year, :month do |t,args| args.with_defaults(:year => Time.now.strftime('%Y'), :month => Time.now.strftime('%m')) year = args.year month = args.month ... snip ... Webby::Builder.create(fn, :from => tmpl, :locals => {:title => month, :directory => dir, :dirty => ("#{year}.#{month}" == Time.now.strftime('%Y.%m'))}) end end
The month.erb and year.erb templates also need to be changed to support disabling the dirty flag:
title: <%= title %> created_at: <%= Time.now.to_y %> filter: erb <%= 'dirty: true' if dirty %>
Finally, running webby blog:import_posts[typo.db] finishes the import process, populating the content directory with all of the Typo posts.
Edit (2009.04.20): Although this blog post is still technically correct, it’s probably better just to grab the latest versions of my tasks and templates from my github repo. I’ve cleaned up the tasks a bit and added arguments to the blog:post task to specify the date.