Permalink
Browse files

Extracted engine from ThunderboltLabs.com

  • Loading branch information...
1 parent 8ec9ba7 commit 34c6b10ffe539ba10fc850acafbce2a1049dadc5 Tammer Saleh committed Nov 24, 2011
View
@@ -1,2 +1,10 @@
#!/usr/bin/env rake
+require 'bundler/setup'
+
require "bundler/gem_tasks"
+require 'rspec/core/rake_task'
+
+RSpec::Core::RakeTask.new(:spec)
+
+task :default => :spec
+
View
@@ -15,6 +15,20 @@ Gem::Specification.new do |gem|
gem.require_paths = ["lib"]
gem.version = EngineOfWar::VERSION
+ gem.add_dependency 'sinatra'
+ gem.add_dependency "compass"
+ gem.add_dependency "padrino"
+ gem.add_dependency "active_support"
+ gem.add_dependency "builder"
+ gem.add_dependency 'haml'
+ gem.add_dependency 'sass', ">= 3.1.7"
+ gem.add_dependency "RedCloth"
+ gem.add_dependency "coffee-script"
+
gem.add_development_dependency "yard"
gem.add_development_dependency "RedCloth"
+ gem.add_development_dependency "rake"
+ gem.add_development_dependency "rspec"
+ gem.add_development_dependency "capybara"
+
end
View
@@ -1,5 +1,24 @@
-require "engine_of_war/version"
+require 'sinatra'
+require 'compass'
+require "builder"
+require 'haml'
+require 'sass'
+require "RedCloth"
+require "coffee-script"
+require 'padrino-core/application/rendering'
+require 'padrino-helpers'
+require 'active_support/hash_with_indifferent_access'
+require 'active_support/core_ext/object/blank'
+require 'json'
+
+module EngineOfWar; end
+
+require 'engine_of_war/version'
+require 'engine_of_war/extensions/string'
+require 'engine_of_war/my_red_cloth_template'
+require 'engine_of_war/layout'
+require 'engine_of_war/page'
+require 'engine_of_war/page_collection'
+require 'engine_of_war/recommendation'
+require 'engine_of_war/app'
-module EngineOfWar
- # Your code goes here...
-end
View
@@ -0,0 +1,67 @@
+class EngineOfWar::App < Sinatra::Base
+ register Padrino::Rendering
+ register Padrino::Helpers
+
+ Compass.configuration do |config|
+ config.project_path = File.dirname(__FILE__)
+ config.sass_dir = 'views/css'
+ end
+
+ set :haml, { :format => :html5 }
+ set :scss, Compass.sass_engine_options
+ # set :root, File.expand_path(File.dirname(__FILE__) + '/../')
+ set(:config) { File.expand_path(root + '/config/') }
+
+ def render_page_with_layout(page)
+ render_page(page, :layout => "layouts/#{page.layout}", :layout_engine => :haml)
+ end
+
+ get "/posts.atom" do
+ content_type :rss
+ builder do |xml|
+ xml.instruct! :xml, :version => '1.0'
+ xml.rss :version => "2.0" do
+ xml.channel do
+ xml.title "Thunderbolt Labs"
+ xml.link "http://#{request.host}"
+
+ collection("posts").each do |post|
+ xml.item do
+ xml.title post.meta[:title]
+ xml.link "http://#{request.host}#{post.url}"
+ xml.description render_page(post)
+ xml.pubDate post.meta[:date].rfc822
+ xml.guid "http://#{request.host}#{post.url}"
+ end
+ end
+ end
+ end
+ end
+ end
+
+ get %r{^/([^.]+)$} do |name|
+ render_page_with_layout(EngineOfWar::Page.new(name))
+ end
+
+ get "/" do
+ render_page_with_layout(EngineOfWar::Page.new(:index))
+ end
+
+ get "/*.*" do |name, ext|
+ content_type ext
+ render :"#{name}", :layout => false
+ end
+
+ helpers do
+ def render_page(page, opts = {})
+ opts[:locals] ||= {}
+ opts[:locals][:meta] = page.meta
+ opts[:locals][:page] = page
+ send(page.engine, page.source, opts)
+ end
+
+ def collection(dir)
+ EngineOfWar::PageCollection.new(dir)
+ end
+ end
+end
@@ -0,0 +1,10 @@
+class String
+ def unindent
+ gsub /^#{self[/\A\s*/]}/, ''
+ end
+
+ def uncomment(comment = "//")
+ gsub(%r{^#{comment}\s*}, '')
+ end
+end
+
@@ -0,0 +1,29 @@
+class Layout
+ attr_reader :page
+
+ def initialize(page)
+ @page = page
+ end
+
+ def name
+ potential_layouts.first + ".html"
+ end
+
+ def potential_layouts
+ [layout_from_directory, layout_from_meta, default_layout].reject(&:blank?).compact.select do |f|
+ File.exists?(File.join(page.views_root, "layouts", "#{f}.html.haml"))
+ end
+ end
+
+ def layout_from_directory
+ File.dirname(page.request_path).sub!(%r{^[/.]}, "")
+ end
+
+ def layout_from_meta
+ page.meta[:layout]
+ end
+
+ def default_layout
+ "application"
+ end
+end
@@ -0,0 +1,78 @@
+class EngineOfWar::RedClothTemplate < Tilt::RedClothTemplate
+ Tilt.register self, "textile"
+
+ BASE_IMAGE_URL = "/images"
+ include Padrino::Helpers::TagHelpers
+
+ def prepare
+ @engine = RedCloth.new(image_filter(code_filter(data)))
+ @output = nil
+ end
+
+ private
+
+ def code_filter(txt)
+ txt.gsub(/@@@ *(\w*)\r?\n? *(.+?)\r?\n?@@@/m) do
+ klass = $1.present? ? " class=\"#{$1.downcase}\"" : ""
+ "<pre><code#{klass}>#{$2}</code></pre>"
+ end
+ end
+
+ def image_filter(txt)
+ txt.gsub(/^%([<>]?)([0-9a-zA-Z_.-]+)([^%]*)%/) do
+ float = $1
+ image_id = $2
+ size = $3
+
+ float = :right if float == '>'
+ float = :left if float == '<'
+
+ uploaded_image_tag(image_id, :size => size, :float => float)
+ end
+ end
+
+ def uploaded_image_tag(image_name, opts = {})
+ opts.symbolize_keys
+
+ opts[:size] = "original" if opts[:size].blank?
+ opts[:size].strip!
+
+ basename, ext = image_name.split('.')
+ image_src = "#{BASE_IMAGE_URL}/#{basename}/#{opts[:size]}.#{ext}"
+ meta = meta_for_image(basename)
+
+ return "<div class='warning'>unknown image #{image_name}</div>" unless File.directory?(image_basedir(basename))
+
+ image_options = { :src => image_src }
+ image_options[:class] = "float-#{opts[:float]}" if opts[:float]
+ image_options[:alt] = meta[:description] if meta[:description]
+
+ href = meta[:source_url]
+
+ img_tag = content_tag :img, "", image_options
+ if href
+ return "<a href='#{href}'>#{img_tag}</a>"
+ else
+ return img_tag
+ end
+ end
+
+ def image_basedir(basename)
+ File.join(EngineOfWar::App.settings.public, BASE_IMAGE_URL, basename)
+ end
+
+ def meta_for_image(basename)
+ file = File.join(image_basedir(basename), "meta.yml")
+ if File.exist?(file)
+ YAML.load_file(file).delete_if {|k, v| v.blank? }
+ else
+ {}
+ end
+ end
+
+ # Required to confuse padrino
+ def block_is_template?(_)
+ false
+ end
+end
+
View
@@ -0,0 +1,68 @@
+class EngineOfWar::Page
+ YAML_REGEXP = /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
+
+ attr_reader :request_path, :views_root, :meta, :source
+
+ def initialize(request_path)
+ @views_root = EngineOfWar::App.settings.views
+ @request_path = normalize_path(request_path)
+ @entire_source = File.read(template_path)
+ @meta, @source = split_body
+ end
+
+ def layout
+ Layout.new(self).name
+ end
+
+ def url
+ request_path
+ end
+
+ def engine
+ template_path.split(".").last.to_sym
+ end
+
+ def github_edit_url
+ relative_template_path = template_path.sub(views_root, "views")
+ "https://github.com/thunderboltlabs/thunderboltlabs/edit/master/#{relative_template_path}"
+ end
+
+ private
+
+ def normalize_path(path)
+ path = path.to_s
+ path.sub!(%r{/$}, "")
+ path.start_with?("/") ? path : "/#{path}"
+ end
+
+ def split_body
+ data = {}
+ body = @entire_source
+ if @entire_source =~ YAML_REGEXP
+ data = hash_from_yaml($1)
+ body = @entire_source.split(YAML_REGEXP).last
+ end
+
+ [HashWithIndifferentAccess.new(data), body]
+ end
+
+ def hash_from_yaml(yaml)
+ begin
+ return YAML.load(yaml)
+ rescue ArgumentError => e
+ raise e, "#{e.message}:\n#{yaml.inspect}"
+ end
+ end
+
+ def template_path
+ first_template_matching(request_path)
+ end
+
+ def first_template_matching(name)
+ pattern = File.join(views_root, "#{name}.html.*")
+ candidates = Dir[pattern]
+ raise Sinatra::NotFound, "Could find no files matching #{pattern}" if candidates.empty?
+ candidates.first
+ end
+end
+
@@ -0,0 +1,47 @@
+class EngineOfWar::PageCollection < Array
+ attr_accessor :collection_root
+
+ def initialize(collection_root)
+ super()
+ self.collection_root = collection_root
+ self.concat(pages)
+ end
+
+ private
+
+ def pages
+ unsorted_pages.sort_by do |page|
+ page.meta[:date]
+ end.reverse
+ end
+
+ def unsorted_pages
+ page_template_paths.map do |file_path|
+ EngineOfWar::Page.new(file_path)
+ end
+ end
+
+ def page_template_paths
+ page_files.map do |full_path|
+ template_path_for(full_path)
+ end
+ end
+
+ def template_path_for(full_path)
+ full_path[views_root] = ""
+ full_path[%r{\.[^/]*}] = ""
+ full_path
+ end
+
+ def page_files
+ Dir[File.join(pages_root, "**/*")]
+ end
+
+ def pages_root
+ File.join(views_root, collection_root)
+ end
+
+ def views_root
+ EngineOfWar::App.settings.views
+ end
+end
Oops, something went wrong.

0 comments on commit 34c6b10

Please sign in to comment.