<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/url_helper.rb</filename>
    </added>
    <added>
      <filename>spec/url_helper_spec.rb</filename>
    </added>
    <added>
      <filename>tasks/db.rake</filename>
    </added>
    <added>
      <filename>web/blues_hero/css/application.css</filename>
    </added>
    <added>
      <filename>web/blues_hero/helpers/blues_hero_helper.rb</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/batjeremy.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/black_header.png</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/black_header_with_slogan.png</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/chris.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/hawk-karissa.png</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/header.png</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/jeremy.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/jocelyn.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/karen.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/karissa.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/kevin.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/lessa.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/lucy.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/menu_bar.png</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/simple_header.png</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/solomon.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/supertopher.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/supertopher_and_batjeremy.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/teacher_contact_sheet.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/images/topher.jpg</filename>
    </added>
    <added>
      <filename>web/blues_hero/index.html.erb</filename>
    </added>
    <added>
      <filename>web/blues_hero/layouts/application.html.erb</filename>
    </added>
    <added>
      <filename>web/blues_hero/register.html.erb</filename>
    </added>
    <added>
      <filename>web/blues_hero/schedule.html.erb</filename>
    </added>
    <added>
      <filename>web/blues_hero/teachers.html.erb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -11,7 +11,11 @@ end
 desc &quot;generate the site&quot;
 task :generate do
   Dir.chdir(File.dirname(__FILE__)) do
-    SiteGenerator.new(&quot;web/facilitation_patterns&quot;, &quot;public/facilitation_patterns&quot;).generate
-    SiteGenerator.new(&quot;web/challenge&quot;, &quot;public/challenge&quot;).generate
+    sites = %w(blues_hero challenge facilitation_patterns)
+    sites = [ENV[&quot;SITE&quot;]] if ENV[&quot;SITE&quot;]
+      
+    sites.each do |site|
+      SiteGenerator.new(&quot;web/#{site}&quot;, &quot;public/#{site}&quot;).generate
+    end
   end
 end
\ No newline at end of file</diff>
      <filename>Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -12,7 +12,8 @@ require 'yaml'
 $LOAD_PATH &lt;&lt; File.expand_path(File.dirname(__FILE__))
 
 require 'extensions/string'
+require 'url_helper'
 require 'site_generator'
 require 'html_generator'
 require 'pattern'
-require 'pattern_links_extension'
\ No newline at end of file
+require 'pattern_links_extension'</diff>
      <filename>lib/blog.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,78 +3,134 @@ require 'pattern'
 class HtmlGenerator
   def initialize(template_directory)
     @template_directory = template_directory
-    @context = Context.new
-    @layout_directory = File.join(template_directory, &quot;layouts&quot;)
+    @global_context = GlobalContext.new
     load_patterns
   end
   
-  def process(file_name, content, apply_layout = true)
+  def write_page(in_file, out_file)
+    File.open(out_file, &quot;w&quot;) do |f| 
+      f &lt;&lt; process_file(in_file)
+    end
+  end
+
+  def process_file(file, context = new_context, apply_layout = true)
+    process(File.basename(file), File.read(file), context, apply_layout)
+  rescue
+    $stderr.puts &quot;error processing #{file}&quot;
+    raise
+  end  
+
+  def process(file_name, content, context = new_context, apply_layout = true)
     file_name, extension = file_name.split_filename
 
     case extension
     when 'erb'
-      content = ERB.new(content, 0, &quot;%&lt;&gt;&quot;).result(@context.get_binding)
+      content = ERB.new(content, 0, &quot;%&lt;&gt;&quot;).result(context.get_binding)
       
     when 'red'
       redcloth = RedCloth.new(content)
-      redcloth.patterns = @context.patterns
+      redcloth.patterns = context.patterns
       content = redcloth.to_html(:html, :textile, :refs_patterns)
       
     when 'yml'
       content = YAML::load(content) rescue raise(&quot;error reading #{file_name}: #{$!.message}&quot;)
             
     when 'pattern'
-      @context.pattern = Pattern.new(file_name.to_sym, content)
-      content = use_layout(&quot;pattern&quot;)
+      context.pattern = Pattern.new(file_name.to_sym, content)
+      context.layout :pattern
+      content = process_file(context.layout_template, context, false)
+      context.layout :application
 
-    when 'bald'
-      return content
-      
     when nil
-      if apply_layout
-        @context.content = content
-        return use_layout(&quot;application&quot;)
+      if apply_layout &amp;&amp; context.layout_template
+        context.content = content
+        return process_file(context.layout_template, context, false)
       else
         return content
       end
     end
 
-    return process(file_name, content, apply_layout)
+    return process(file_name, content, context, apply_layout)
   end
   
-  def use_layout(name)
-    files = Dir[&quot;#{@layout_directory}/#{name}.*&quot;]
-    raise &quot;couldn't find layout #{name}&quot; if files.empty?
-    process_file(files.first, false)
-  end
+  private
   
   def load_patterns
-    unless @context.patterns
-      @context.patterns = Patterns.load(@template_directory)
-      @context.patterns_by_category = {}
-      @context.patterns.each do |pattern|
-        (@context.patterns_by_category[pattern.category] ||= []) &lt;&lt; pattern
+    unless @global_context.patterns
+      @global_context.patterns = Patterns.load(@template_directory)
+      @global_context.patterns_by_category = {}
+      @global_context.patterns.each do |pattern|
+        (@global_context.patterns_by_category[pattern.category] ||= []) &lt;&lt; pattern
       end
     end
   end
-      
-  def process_file(file, apply_layout = true)
-    process(File.basename(file), File.read(file), apply_layout)
+  
+  def new_context
+    PageContext.new(@template_directory, @global_context)
   end
   
-  def write_page(in_file, out_file)
-    File.open(out_file, &quot;w&quot;) do |f| 
-      f &lt;&lt; process_file(in_file)
+  class PageContext
+    include UrlHelper
+    attr_accessor :global_context, :layout_template, :pattern, :content
+    
+    def initialize(template_directory, global_context)
+      @template_directory, @global_context = template_directory, global_context
+      layout(:application) rescue nil
     end
-  end
     
-  class Context
-    attr_accessor :pattern, :patterns, :patterns_by_category, :content
+    def layout(name)
+      if name
+        files = Dir[File.join(@template_directory, 'layouts', &quot;#{name}.*&quot;)]
+        raise &quot;couldn't find layout #{name}&quot; if files.empty?
+        @layout_template = files.first
+      else
+        @layout_template = nil
+      end
+    end
+    
+    def helper(name)
+      file_name = &quot;#{name}_helper&quot;
+      class_name = file_name.classify
+      helper = begin
+        class_name.constantize
+      rescue NameError # this constant hasn't been loaded yet
+        require File.join(@template_directory, &quot;helpers&quot;, file_name)
+        class_name.constantize
+      end
+      
+      metaclass.send(:include, helper)
+    end
+    
+    def content_for(name) 
+      metaclass.send(:attr_accessor, &quot;content_for_#{name}&quot;.to_sym)
+      send(&quot;content_for_#{name}=&quot;.to_sym, yield)
+    end
     
     def get_binding
       binding
     end
     
+    def method_missing(sym, *args)
+      return @global_context.send(sym, *args) if @global_context.respond_to?(sym)
+
+      name = sym.to_s
+      if name.starts_with?(&quot;content_for_&quot;) &amp;&amp; name.ends_with?(&quot;?&quot;)
+        return !!instance_variable_get(&quot;@#{name[0..-2]}&quot;)
+      end
+
+      super
+    end
+    
+    private
+    
+    def metaclass 
+      class &lt;&lt; self; self; end # according to why...
+    end
+  end
+  
+  class GlobalContext
+    attr_accessor :patterns, :patterns_by_category
+    
     def link_to(name, url = nil)
       url ||= name + &quot;.html&quot;
       &quot;&lt;a href='#{url}'&gt;#{name}&lt;/a&gt;&quot;</diff>
      <filename>lib/html_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -33,7 +33,7 @@ class SiteGenerator
   end
   
   def excluded?(file)
-    File.basename(file) == &quot;layouts&quot;
+    File.directory?(file) &amp;&amp; %w(layouts helpers).include?(File.basename(file))
   end
   
   def resource?(file)</diff>
      <filename>lib/site_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,2 +1,3 @@
 facilitation_patterns
-challenge
\ No newline at end of file
+challenge
+blues_hero</diff>
      <filename>public/.gitignore</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,82 @@
 require File.dirname(__FILE__) + '/spec_helper'
 
 describe HtmlGenerator do
+  include FileSandbox
+  attr_reader :generator
+  
   before do
-    @gen = HtmlGenerator.new(nil)
+    @generator = HtmlGenerator.new(sandbox.root)
+  end
+  
+  describe &quot;layouts&quot; do
+    it &quot;should show html w/ default layout&quot; do
+      sandbox.new :file =&gt; 'layouts/application.html.erb', 
+                  :with_contents =&gt; &quot;&lt;html&gt;&lt;body&gt;&lt;%= content %&gt;&lt;/body&gt;&lt;/html&gt;&quot;
+
+      process(&quot;*.html&quot;, &quot;foobar&quot;).should == &quot;&lt;html&gt;&lt;body&gt;foobar&lt;/body&gt;&lt;/html&gt;&quot;
+    end
+    
+    it &quot;should be able to specify a layout&quot; do
+      sandbox.new :file =&gt; 'layouts/my_layout.html.erb', 
+                  :with_contents =&gt; &quot;&lt;html&gt;&lt;%= content %&gt;&lt;/html&gt;&quot;
+
+      process(&quot;*.html.erb&quot;, &quot;% layout 'my_layout'\nfoobar&quot;).should == 
+                                                              &quot;&lt;html&gt;foobar&lt;/html&gt;&quot;
+      process(&quot;*.html.erb&quot;, &quot;% layout :my_layout\nfoobar&quot;).should == 
+                                                              &quot;&lt;html&gt;foobar&lt;/html&gt;&quot;
+    end
+    
+    it &quot;should forget about layout after layout is specified&quot; do
+      sandbox.new :file =&gt; 'layouts/application.html.erb', :with_contents =&gt; &quot;app&quot;
+      sandbox.new :file =&gt; 'layouts/foo.html.erb', :with_contents =&gt; &quot;foo&quot;
+
+      process(&quot;*.html&quot;, &quot;&quot;).should == &quot;app&quot;
+      process(&quot;*.html.erb&quot;, &quot;% layout 'foo'&quot;).should == &quot;foo&quot;
+      process(&quot;*.html&quot;, &quot;&quot;).should == &quot;app&quot;      
+    end
+    
+    it &quot;should allow a nil layout&quot; do
+      process(&quot;*.html.erb&quot;, &quot;% layout nil\nsomething&quot;).should == &quot;something&quot;
+      process(&quot;*.html.erb&quot;, &quot;% layout false\nsomething&quot;).should == &quot;something&quot;
+    end
+  end
+  
+  describe &quot;helpers&quot; do
+    before do
+      sandbox.new :file =&gt; 'helpers/test_helper.rb', :with_contents =&gt; &quot;
+        module TestHelper
+          def some_test_method
+            'hello world'
+          end
+        end&quot;
+      sandbox.new :file =&gt; &quot;layouts/application.html.erb&quot;, 
+                  :with_contents =&gt; &quot;&lt;%= content %&gt;&quot;
+    end
+    
+    it &quot;should be able to use a helper&quot; do
+      process(&quot;*.html.erb&quot;, &quot;% helper 'test'\n&lt;%= some_test_method %&gt;&quot;).
+                should == &quot;hello world&quot;
+    end
+  end
+  
+  describe &quot;content_for&quot; do
+    it &quot;should remember a string value&quot; do
+      sandbox.new :file =&gt; &quot;layouts/application.html.erb&quot;, 
+                  :with_contents =&gt; &quot;head:&lt;%= content_for_head %&gt;&quot;
+      process(&quot;*.html.erb&quot;, &quot;% content_for(:head) { 'bob' }&quot;).should == &quot;head:bob&quot;
+    end
+    
+    it &quot;should know if there is content for a given key&quot; do
+      sandbox.new :file =&gt; &quot;layouts/application.html.erb&quot;, 
+                  :with_contents =&gt; &quot;head:&lt;%= content_for_head? %&gt;, tail:&lt;%= content_for_tail? %&gt;&quot;
+                  
+      process(&quot;*.html.erb&quot;, &quot;&quot;).should == &quot;head:false, tail:false&quot;
+      process(&quot;*.html.erb&quot;, &quot;% content_for(:tail) { 'a' }&quot;).should == &quot;head:false, tail:true&quot;
+      process(&quot;*.html.erb&quot;, &quot;% content_for(:head) { 'bob' }\n% content_for(:tail) {'a'}&quot;).should == &quot;head:true, tail:true&quot;
+    end
+  end
+  
+  def process(extensions, content)
+    generator.process(extensions, content)
   end
 end
\ No newline at end of file</diff>
      <filename>spec/html_generator_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,3 +2,6 @@ require File.dirname(__FILE__) + &quot;/../lib/blog&quot;
 
 gem 'rspec'
 require 'spec'
+
+gem 'file_sandbox', '&gt;= 0.4'
+require 'file_sandbox_behavior'</diff>
      <filename>spec/spec_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,7 +18,7 @@
       &lt;%= link_to &quot;the concept&quot;, &quot;concept.html&quot; %&gt;
       &lt;%= link_to &quot;the schedule&quot;, &quot;schedule.html&quot; %&gt;
       &lt;%= link_to &quot;the teachers&quot;, &quot;teachers.html&quot; %&gt;
-      &lt;%= link_to &quot;register&quot; %&gt;
+      &lt;%= link_to &quot;register&quot;, &quot;register.html&quot; %&gt;
     &lt;/div&gt;
     &lt;div class=&quot;left_side&quot;&gt;
       &lt;%= content %&gt;</diff>
      <filename>web/challenge/layouts/application.html.erb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>lib/tasks/db.rake</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>dabfc23c51035776bbe0c1b16bcfea123031e035</id>
    </parent>
  </parents>
  <author>
    <name>jeremylightsmith</name>
    <email>jeremy.lightsmith@gmail.com</email>
  </author>
  <url>http://github.com/jeremylightsmith/blog/commit/cdab3b93433df4f8a1569c3ca83b589a3a65fcb9</url>
  <id>cdab3b93433df4f8a1569c3ca83b589a3a65fcb9</id>
  <committed-date>2008-11-03T00:25:29-08:00</committed-date>
  <authored-date>2008-11-03T00:25:29-08:00</authored-date>
  <message>generalized stuff</message>
  <tree>dcbd978395b285c5b4a78502fe848137cc711c27</tree>
  <committer>
    <name>jeremylightsmith</name>
    <email>jeremy.lightsmith@gmail.com</email>
  </committer>
</commit>
