diff --git a/Makefile b/Makefile index 4770350..075c382 100644 --- a/Makefile +++ b/Makefile @@ -1,21 +1,27 @@ -JSON=harp.json $(shell echo public/*.json) $(shell echo public/*/*.json) -EJS=$(shell echo public/*.ejs) $(shell echo public/*/*.ejs) -JAVASCRIPTS=$(shell echo public/js/*.js) -STYLESHEETS=$(shell echo public/css/*.css) -POSTS=$(shell echo public/posts/*.html) $(shell echo public/posts/*.md) - all: compile compile: posts @echo ./bin/compile.sh -posts: $(POSTS) +posts: @echo ./bin/posts.rb public public publish: compile @echo - ./bin/publish.sh --delete public/ + ./bin/publish.sh www/.htaccess + ./bin/publish.sh www/favicon.ico + ./bin/publish.sh www/feed.xml + ./bin/publish.sh www/*.html + ./bin/publish.sh www/*.png + ./bin/publish.sh www/f/ + ./bin/publish.sh --delete www/Chalk + ./bin/publish.sh --delete www/css + ./bin/publish.sh --delete www/images + ./bin/publish.sh --delete www/js + ./bin/publish.sh --delete www/posts + ./bin/publish.sh --delete www/projects + ./bin/publish.sh --delete www/tweets -.PHONY: publish +.PHONY: compile publish diff --git a/bin/compile.sh b/bin/compile.sh index 48ad6dc..bbde29a 100755 --- a/bin/compile.sh +++ b/bin/compile.sh @@ -1,8 +1,11 @@ #!/bin/bash -harp compile public public +bin/rss.rb public -for FILENAME in public/posts/*.html public/projects/*.html; do +mkdir -p www +harp compile public www + +for FILENAME in www/*.html www/posts/*.html www/projects/*.html; do [[ "$FILENAME" = "index.html" ]] && continue DIRNAME="${FILENAME%.html}" diff --git a/bin/posts.rb b/bin/posts.rb deleted file mode 100755 index a5330e8..0000000 --- a/bin/posts.rb +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env ruby -# encoding: utf-8 - -require 'time' -require 'rubygems' -require 'bundler/setup' -require 'builder' -require 'json' -require 'rdiscount' -require 'mustache' - -DEFAULT_KEYWORDS = %w[samsonjs sjs sami samhuri sami samhuri samhuri.net] - -def main - srcdir = ARGV.shift.to_s - destdir = ARGV.shift.to_s - Dir.mkdir(destdir) unless File.exists?(destdir) - unless File.directory? srcdir - puts 'usage: blog.rb ' - exit 1 - end - b = Blag.new srcdir, destdir - puts 'title: ' + b.title - puts 'subtitle: ' + b.subtitle - puts 'url: ' + b.url - puts "#{b.posts.size} posts" - b.generate! - puts 'done blog' -end - -class Blag - attr_accessor :title, :subtitle, :url - - def self.go! src, dest - self.new(src, dest).generate! - end - - def initialize src, dest - @src = src - @dest = dest - read_blog - end - - def generate! - generate_posts_json - generate_rss - end - - def generate_posts_json - posts_data = posts.reverse.inject({}) do |all, p| - all[p[:slug]] = { - title: p[:title], - date: p[:date], - timestamp: p[:timestamp], - tags: p[:tags], - author: p[:author], - url: p[:relative_url], - link: p[:link], - styles: p[:styles] - }.delete_if { |k, v| v.nil? } - - all - end - json = JSON.pretty_generate posts_data - filename = File.join @dest, 'posts', '_data.json' - File.open(filename, 'w') { |f| f.puts json } - - filename = File.join @dest, '_data.json' - data = JSON.parse File.read(filename) - post = latest_post - data['latest'] = posts_data[post[:slug]].merge('body' => post[:body]) - json = JSON.pretty_generate data - File.open(filename, 'w') { |f| f.puts json } - end - - def generate_rss - # posts rss - File.open(rss_file, 'w') { |f| f.puts rss_for_posts.target! } - end - - def latest_post - posts.first - end - - def posts - prefix = @src + '/posts/' - @posts ||= Dir[File.join(prefix, '*')].sort.reverse.map do |filename| - next if File.directory?(filename) || filename =~ /_data\.json/ - - lines = File.readlines filename - post = { - slug: filename.sub(prefix, '').sub(/\.(html|md)$/i, '') - } - loop do - line = lines.shift.strip - m = line.match /^(\w+):/ - if m && param = m[1].downcase - post[param.to_sym] = line.sub(Regexp.new('^' + param + ':\s*', 'i'), '').strip - elsif line.match /^----\s*$/ - lines.shift while lines.first.strip.empty? - break - else - puts "ignoring unknown header: #{line}" - end - end - if post[:styles] - post[:styles] = post[:styles].split(/\s*,\s*/) - end - post[:type] = post[:link] ? :link : :post - post[:title] += " →" if post[:type] == :link - post[:tags] = (post[:tags] || '').split(/\s*,\s*/) - post[:relative_url] = '/posts/' + post[:slug] - post[:url] = @url + post[:relative_url] - post[:timestamp] = post[:timestamp].to_i - post[:content] = lines.join - post[:body] = RDiscount.new(post[:content], :smart).to_html - post[:rfc822] = Time.at(post[:timestamp]).rfc822 - post - end.compact.sort { |a, b| b[:timestamp] <=> a[:timestamp] } - end - - - private - - def blog_file - File.join(@src, '_data.json') - end - - def read_blog - blog = JSON.parse(File.read(blog_file)) - @title = blog['title'] - @subtitle = blog['subtitle'] - @url = blog['url'] - end - - def rss_template(type) - if type == :post - @post_rss_template ||= File.read(File.join('templates', 'post.rss.html')) - elsif type == :link - @link_rss_template ||= File.read(File.join('templates', 'link.rss.html')) - else - raise 'unknown post type: ' + type - end - end - - def rss_file - File.join @dest, 'sjs.rss' - end - - def rss_html post - Mustache.render rss_template(post[:type]), post: post - end - - def rss_for_posts options = {} - title = options[:title] || @title - subtitle = options[:subtitle] || @subtitle - url = options[:url] || @url - rss_posts ||= options[:posts] || posts[0, 10] - - xml = Builder::XmlMarkup.new - xml.instruct! :xml, :version => '1.0' - xml.instruct! 'xml-stylesheet', :href => 'http://samhuri.net/css/style.css', :type => 'text/css' - - xml.rss :version => '2.0' do - xml.channel do - xml.title title - xml.description subtitle - xml.link url - xml.pubDate posts.first[:rfc822] - - rss_posts.each do |post| - xml.item do - xml.title post[:title] - xml.description rss_html(post) - xml.pubDate post[:rfc822] - xml.author post[:author] - xml.link post[:link] || post[:url] - xml.guid post[:url] - end - end - end - end - xml - end - -end - -main if $0 == __FILE__ diff --git a/bin/publish.sh b/bin/publish.sh index 5e5f8b7..4eeea1b 100755 --- a/bin/publish.sh +++ b/bin/publish.sh @@ -8,20 +8,40 @@ bail() { exit 1 } -publish_host=samhuri.net -publish_dir=samhuri.net/public/ +publish_host="samhuri.net" +publish_dir="samhuri.net/public/" +prefix="" +delete="" -# test -if [[ "$1" = "-t" ]]; then - prefix=echo - shift -fi +break_while=0 +while [[ $# > 1 ]]; do -# --delete, passed to rsync -if [[ "$1" = "--delete" ]]; then - delete="--delete" - shift -fi + arg="$1" + + case "$arg" in + + -t|--test) + prefix=echo + shift + ;; + + -d|--delete) + # passed to rsync + delete="--delete" + shift + ;; + + # we're at the paths, no more options + *) + break_while=1 + break + ;; + + esac + + [[ $break_while -eq 1 ]] && break + +done if [[ $# -eq 0 ]]; then if [[ "$delete" != "" ]]; then diff --git a/bin/rss.rb b/bin/rss.rb new file mode 100755 index 0000000..24b2233 --- /dev/null +++ b/bin/rss.rb @@ -0,0 +1,153 @@ +#!/usr/bin/env ruby +# encoding: utf-8 + +require 'time' +require 'rubygems' +require 'bundler/setup' +require 'builder' +require 'json' +require 'rdiscount' +require 'mustache' + +def main + dir = ARGV.shift.to_s + unless File.directory? dir + puts 'usage: rss.rb ' + exit 1 + end + b = Blag.new dir + b.generate! +end + +class Blag + + def self.go! dir + self.new(dir).generate! + end + + def initialize dir + @dir = dir + end + + def generate! + generate_latest_post_json + generate_rss + end + + def generate_latest_post_json + post = latest_post + data['latest'] = { + title: post['title'], + date: post['date'], + timestamp: post['timestamp'], + tags: post['tags'], + author: post['author'], + url: post['relative_url'], + link: post['link'], + styles: post['styles'], + body: post['body'] + }.delete_if { |k, v| v.nil? } + json = JSON.pretty_generate data + File.open(data_file, 'w') { |f| f.puts json } + end + + def generate_rss + File.open(rss_file, 'w') { |f| f.puts feed_xml.target! } + end + + def latest_post + posts.first + end + + def posts + @posts ||= begin + prefix = @dir + '/posts/' + json = File.read File.join(prefix, '_data.json') + data = JSON.parse json + data.map do |slug, post| + filename = File.join prefix, slug + '.md' + content = File.read filename + post['slug'] = slug + post['type'] = post['link'] ? :link : :post + post['title'] += " →" if post['type'] == :link + post['relative_url'] = '/posts/' + slug + post['url'] = root_url + post['relative_url'] + post['content'] = content + post['body'] = RDiscount.new(post['content'], :smart).to_html + post['rfc822'] = Time.at(post['timestamp']).rfc822 + post + end.sort_by { |p| -p['timestamp'] }.first(10) + end + end + + def title + data['title'] + end + + def subtitle + data['subtitle'] + end + + def root_url + data['url'] + end + + +private + + def data_file + File.join @dir, '_data.json' + end + + def data + @data ||= JSON.parse File.read(data_file) + end + + def rss_template(type) + if type == :post + @post_rss_template ||= File.read(File.join('templates', 'post.rss.html')) + elsif type == :link + @link_rss_template ||= File.read(File.join('templates', 'link.rss.html')) + else + raise 'unknown post type: ' + type + end + end + + def rss_file + File.join @dir, 'feed.xml' + end + + def rss_html post + Mustache.render rss_template(post['type']), post: post + end + + def feed_xml + xml = Builder::XmlMarkup.new + xml.instruct! :xml, version: '1.0' + xml.instruct! 'xml-stylesheet', href: 'http://samhuri.net/css/style.css', type: 'text/css' + + xml.rss version: '2.0' do + xml.channel do + xml.title title + xml.description subtitle + xml.link root_url + xml.pubDate posts.first['rfc822'] + + posts.each do |post| + xml.item do + xml.title post['title'] + xml.description rss_html(post) + xml.pubDate post['rfc822'] + xml.author post['author'] + xml.link post['link'] || post['url'] + xml.guid post['url'] + end + end + end + end + xml + end + +end + +main if $0 == __FILE__