Created
July 15, 2011 15:15
-
-
Save ratbeard/1084877 to your computer and use it in GitHub Desktop.
Middleman feature for generated pages based off entries in a data yaml file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link rel="stylesheet" href="/stylesheets/news/detail.css" /> | |
<section> | |
<div class="module central content"> | |
<div class="post"> | |
<h2><%= article.title %></h2> | |
<%= article.content %> | |
</div> | |
</div> | |
</section> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# DataPages allow you to create generated pages for middleman (i.e. there is no actual | |
# template file backing up the page). | |
# | |
# It requires a yaml data file that consists of an array of entities, each of which must | |
# have a `slug` property, which is used for the url of that page. If a `title` property | |
# exists, it will set it for `page.data.title`. | |
# | |
# Sample config | |
# | |
# # Custom Feature to allow generated pages like: '/news/title-of-article', based off news.yml | |
# require 'lib/data_pages' | |
# activate DataPages | |
# data_page \ | |
# "/news/:slug", # sinatra route | |
# :data => 'news', # name of data yaml file | |
# :template => 'news/_article.html.erb', # template to render for each entity | |
# :name => :article, # local variable name to reference inside the template | |
# :build_path => 'news/' # when generating the pages with mm-build, prefix slug with this (to match the route above) | |
# | |
module DataPages | |
class << self | |
def registered(app) | |
app.extend ClassMethods | |
end | |
alias :included :registered | |
end | |
module ClassMethods | |
def data_page(url, options={}) | |
# Capture app for use inside route handler to add page data | |
app = self | |
# Store the data_page info for use by mm-build | |
set :data_page_list, [] unless respond_to? :data_page_list | |
self.data_page_list << {:url => url}.merge(options.dup) | |
# Read parameters | |
template = options.delete(:template) || raise("data_page needs a :template parameter") | |
data_key = options.delete(:data) || raise("data_page needs a :data parameter") | |
entity_name = options.delete(:name) || raise("data_page needs a :name parameter") | |
# Copied from core_extension/routing.rb | |
url = url.gsub(%r{#{settings.index_file}$}, "") | |
url = url.gsub(%r{(\/)$}, "") if url.length > 1 | |
paths = [url] | |
paths << "#{url}/" if url.length > 1 && url.split("/").last.split('.').length <= 1 | |
# Tweak, add starting root slash | |
paths << "/#{path_to_index(url)}" | |
#puts "!!! making route", *paths | |
paths.each do |p| | |
get(p) do | |
# My logic | |
slug = URI.escape(params[:slug].chomp(".html")) | |
entities = data.send(data_key) | |
# Find the entity for this requests slug. | |
# Need to double escape slug, since escape returns '%E64' when the url | |
# might be '%e64' | |
unless entity = entities.find {|e| URI.escape(URI.unescape(e.slug)) == slug } | |
#require 'ruby-debug'; debugger | |
$stderr.puts "Couldnt find slug #{slug.inspect}" | |
pass | |
end | |
# Set page title if entity has that attribute | |
if title = entity.title | |
app.data_content("page", {:title => title}) | |
end | |
locals = {} | |
locals[entity_name] = entity | |
# Copied from base.rb#process_request | |
old_layout = settings.layout | |
settings.set :layout, options[:layout] if !options[:layout].nil? | |
layout = if settings.layout | |
if options[:layout] == false || request.path_info =~ /\.(css|js)$/ | |
false | |
else | |
settings.fetch_layout_path(settings.layout).to_sym | |
end | |
else | |
false | |
end | |
render_options = { :layout => layout } | |
render_options[:layout_engine] = options[:layout_engine] if options.has_key? :layout_engine | |
# Tweak: | |
#result = render(request.path_info, render_options, options[:locals]) | |
result = render(template, render_options, locals) | |
settings.set :layout, old_layout | |
if result | |
content_type mime_type(File.extname(request.path_info)), :charset => 'utf-8' | |
status 200 | |
body result | |
else | |
status 404 | |
end | |
end | |
end | |
end | |
end | |
end | |
class Middleman::Builder | |
# Copy paste override to add `rescue source.to_s` | |
def tilt_template(source, *args, &block) | |
config = args.last.is_a?(Hash) ? args.pop : {} | |
destination = args.first || source | |
source = File.expand_path(find_in_source_paths(source.to_s)) rescue source.to_s | |
context = instance_eval('binding') | |
@@rack_test ||= ::Rack::Test::Session.new(::Rack::MockSession.new(SHARED_SERVER)) | |
create_file destination, nil, config do | |
# The default render just requests the page over Rack and writes the response | |
request_path = destination.sub(/^#{SHARED_SERVER.build_dir}/, "") | |
@@rack_test.get(request_path) | |
@@rack_test.last_response.body | |
end | |
end | |
remove_invocation :tilt_template | |
# For each registered data_page, iterate through each entry in the yaml file | |
# and generate the page for that entity. | |
# I'm not sure why this generates each page twice. | |
def build_data_pages | |
return unless SHARED_SERVER.respond_to?(:data_page_list) | |
SHARED_SERVER.data_page_list.each do |data_page| | |
instance = SHARED_SERVER.allocate | |
data = Middleman::CoreExtensions::Data::DataObject.new(instance) | |
entities = data.send(data_page[:data]) | |
entities.each do |entity| | |
source = 'news/' + entity.slug | |
destination = "build/#{data_page[:build_path]}#{entity.slug}/index.html" | |
tilt_template(source, destination, {:force => true}) | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
- title: "Todays update" | |
content: "Today was a good day." | |
slug: what-a-great-day | |
author: space150 | |
- title: "Hot Sauce" | |
content: "Cholula is the best, IMO YMMV." | |
slug: sooo-hot | |
author: space150 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment