diff --git a/LICENSE b/LICENSE
new file mode 100755
index 0000000..1fef251
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2005 Matt McCray, based on code from Typo by Tobias Luetke
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWAR
\ No newline at end of file
diff --git a/README b/README
new file mode 100755
index 0000000..64d0e6a
--- /dev/null
+++ b/README
@@ -0,0 +1,202 @@
+This theme_support version has been updated by Damien Le Berrigaud for Rails 2.0
+http://www.webdrivenblog.com/
+
+= Theme Support for Rails Applications
+
+This plugin provides support for themes to the rails application environment.
+It supports theme specific images, stylesheets, javascripts, and views. The
+views can be in ERb (rhtml) or liquid formats. Optionally, you can configure
+the theme system to ignore any templates except liquid ones.
+
+
+== Usage
+
+This plugin automatically makes any patches needed for theme support. You can
+use the theme_generator to create the file structure needed, or create it
+yourself.
+
+It expects the following theme folder structure.
+
+ $app_root
+ themes/
+ [theme_name]
+ layouts/ <- layout .rhtml or .liquid templates
+ images/
+ stylesheets/
+ javascripts/
+ views/ <- you can override application views
+ about.markdown
+ preview.png
+
+When run in production mode, it will automatically cache the theme files so that
+the web-server will deliver them in subsequent requests.
+
+It bears noting that, like Typo, this will mean your apache/fcgi process will need
+write permissions. This could be a possible security vulnerability.
+
+With that in mind, it is best to pre-cache all of the theme files by using the
+included rake tasks:
+
+ $ rake theme_create_cache
+
+The theme file cache generates the following file structure:
+
+ $app_root
+ public/
+ themes/
+ [theme_name]/
+ images/
+ stylesheets/
+ javascripts/
+
+There are other rake tasks available:
+
+ - theme_create_cache
+ - theme_remove_cache
+ - theme_update_cache
+
+You specify which theme to use in your controller by using the 'theme' helper.
+It's used just like the 'layout' helper. In fact, you can use them both
+simultaneously. The following will render actions using the 'default' layout
+in the 'blue_bird' theme (theme/blue_bird/layouts/default.rhtml):
+
+ class ApplicationController < ActionController::Base
+ layout 'default'
+
+ theme 'blue_bird'
+
+ ...
+ end
+
+You can also defer the theme lookup to a controller method:
+
+ class ApplicationController < ActionController::Base
+ layout 'default'
+
+ theme :get_theme
+
+ def get_theme
+
+ # If you let the user choose their own theme, you might
+ # add a User#theme field...
+
+ current_user.theme
+ end
+
+ ...
+ end
+
+
+Note: By setting the theme in the ApplicationController you can set
+the theme for the whole application.
+
+In your application views, there are theme specific helper tags
+available to you. For ERb templates they are:
+
+ - theme_image_tag
+ - theme_image_path
+ - theme_javascript_include_tag
+ - theme_javascript_path
+ - theme_stylesheet_link_tag
+ - theme_stylesheet_path
+
+For liquid templates there is a single helper, themeitem, that will determine
+the path base on the theme file extension. Here's how you'd use it:
+
+
+ ...
+
+
+The output from those two calls are:
+
+
+ ...
+
+
+New in version 1.4 is ActionMailer support. Note, this is still experimental. However,
+if you would like your themes to be able to override your ActionMailer views, you can
+send the theme in your deliver_* method call. For example, assuming we have an ActionMailer
+class named Mailer, and have implemented theme_support as shown above, here's how you would
+allowing themes in emails:
+
+
+ def send_email
+ Mailer.deliver_my_email( 'a variable', :theme=>get_theme )
+ end
+
+
+== Contributors
+
+The theme_support pluging includs patches from the following:
+
+* agkr
+* D.J. Vogel
+
+Thanks guys!
+
+== Changelog
+
+ 1.4.0 - Better support for Rails 1.1+. Updated the liquid themeitem tag.
+ Liquid layouts are no longer generated by default.Added a couple
+ of patches. One allows theme sub-directories. For example, you
+ can have:
+
+ [theme_dir]
+ stylesheets/
+ admin/
+ main.css
+
+ Added experimental support for themeing ActionMailer classes.
+ They work as normal, if you want to all theme's to override the
+ .rhtml|.liquid views, send the theme in the deliver_* method. For
+ example:
+
+ Mailer.deliver_signup( user, :theme=>get_theme() )
+
+ In that example, `get_theme` is a method on the controller and at
+ the top we've used:
+
+ layout 'default'
+ theme :get_theme
+
+ 1.3.0 - The theme_system component is no longer needed. All of the
+ theme support is driven by a single plugin named, oddly enough,
+ 'theme_support'. Also improved theme route support. Instead of
+ overriding RouteSet#reload, RouteSet#draw is overridden, making
+ the theme support entirely transparent -- hopefully ;-)
+
+ 1.2.2 - More Bug-fixes.
+
+ 1.2.1 - Bug-fixes and documentation clean up.
+
+ 1.2.0 - Updated actionview_ex with the new render_file additions from
+ Typo. Renamed the rake tasks so that they all start with
+ 'theme' (theme_create_cache, theme_remove_cache,
+ theme_update_cache). You can update the system files by running:
+
+ $ ./script/generate theme _system_
+
+ Full support for Liquid templates, as well as an option to only
+ allow Liquid templates in a theme.
+
+ 1.1.1 - Added rake tasks for pre-caching the themes, and removing the
+ cached themes.
+
+ 1.1.0 - [Breaking] Abstraction of the Typo theme system. The themes are
+ now the same as is used in Typo. The theme engine itself is a
+ combination of plugins and a component. No more symlinks, thank
+ goodness.
+
+ 1.0.2 - The current_theme is now retrieved from the controller. Where
+ symlinks are created on *nix systems, shortcuts are created
+ on Windows if Win32Utils is installed.
+
+ 1.0.1 - Added 'themes' directory, theme definition file, and symlinks
+ to the appropriate directories on supported platforms.
+
+ 1.0.0 - Initial release
+
+
+---
+Copyright (c) 2005 Matt McCray, based on code from Typo by Tobias Luetke
+released under the MIT license
diff --git a/generators/theme/USAGE b/generators/theme/USAGE
new file mode 100755
index 0000000..6927cbd
--- /dev/null
+++ b/generators/theme/USAGE
@@ -0,0 +1,15 @@
+NAME
+ theme - Creates the folder structure for a new theme
+
+SYNOPSIS
+ theme [theme_name]
+
+DESCRIPTION
+ This generator creates the folder structure for a new theme. It creates all of
+ the folders for your theme content (images, stylesheets, javascripts, layouts,
+ and views).
+
+EXAMPLE
+ ./script/generate theme default
+
+ This will generate the file structure for a theme named 'default'.
diff --git a/generators/theme/templates/about.markdown b/generators/theme/templates/about.markdown
new file mode 100755
index 0000000..fb3b3c9
--- /dev/null
+++ b/generators/theme/templates/about.markdown
@@ -0,0 +1,5 @@
+### <%= class_name.underscore.humanize.titleize %>
+
+Author: *Me*
+
+This description can be found in themes/<%= file_name %>/about.markdown
diff --git a/generators/theme/templates/layout.liquid b/generators/theme/templates/layout.liquid
new file mode 100755
index 0000000..b24718c
--- /dev/null
+++ b/generators/theme/templates/layout.liquid
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+ {{ content_for_layout }}
+
+
\ No newline at end of file
diff --git a/generators/theme/templates/layout.rhtml b/generators/theme/templates/layout.rhtml
new file mode 100755
index 0000000..a74995c
--- /dev/null
+++ b/generators/theme/templates/layout.rhtml
@@ -0,0 +1,11 @@
+
+
+
+
+ <%%= theme_stylesheet_link_tag '<%= file_name %>' %>
+
+
+ <%%= @content_for_layout %>
+
+
\ No newline at end of file
diff --git a/generators/theme/templates/preview.png b/generators/theme/templates/preview.png
new file mode 100755
index 0000000..182c1f7
Binary files /dev/null and b/generators/theme/templates/preview.png differ
diff --git a/generators/theme/templates/theme.css b/generators/theme/templates/theme.css
new file mode 100755
index 0000000..44471b1
--- /dev/null
+++ b/generators/theme/templates/theme.css
@@ -0,0 +1,7 @@
+/*
+ Main StyleSheet for the '<%= class_name %>' theme
+*/
+
+BODY {
+
+}
\ No newline at end of file
diff --git a/generators/theme/templates/theme.yml b/generators/theme/templates/theme.yml
new file mode 100755
index 0000000..f067d16
--- /dev/null
+++ b/generators/theme/templates/theme.yml
@@ -0,0 +1,4 @@
+enabled: true
+title: <%= class_name.underscore.humanize.titleize %>
+author: Matt McCray
+description: This is the description... All light and fluffy.
diff --git a/generators/theme/templates/views_readme b/generators/theme/templates/views_readme
new file mode 100755
index 0000000..548ce6b
--- /dev/null
+++ b/generators/theme/templates/views_readme
@@ -0,0 +1,13 @@
+# Overriding Views
+
+You can override views by putting custom `rhtml` or `liquid`
+templates in this directory. You use the same folder structure
+as Rails:
+
+ views/
+ [controller_name]/
+ _overriden_partial.rhtml
+ overriden_action.rhtml
+
+*Note:* These are overrides! They will only work if they have
+a matching view in the main rails `app/views` folder.
\ No newline at end of file
diff --git a/generators/theme/theme_generator.rb b/generators/theme/theme_generator.rb
new file mode 100755
index 0000000..170a0e9
--- /dev/null
+++ b/generators/theme/theme_generator.rb
@@ -0,0 +1,27 @@
+class ThemeGenerator < Rails::Generator::NamedBase
+
+ def manifest
+ record do |m|
+ # Theme folder(s)
+ m.directory File.join( "themes", file_name )
+ # theme content folders
+ m.directory File.join( "themes", file_name, "images" )
+ m.directory File.join( "themes", file_name, "javascript" )
+ m.directory File.join( "themes", file_name, "layouts" )
+ m.directory File.join( "themes", file_name, "views" )
+ m.directory File.join( "themes", file_name, "stylesheets" )
+ # Default files...
+ # about
+ m.template 'about.markdown', File.join( 'themes', file_name, 'about.markdown' )
+ # image
+ m.file 'preview.png', File.join( 'themes', file_name, 'images', 'preview.png' )
+ # stylesheet
+ m.template "theme.css", File.join( "themes", file_name, "stylesheets", "#{file_name}.css" )
+ # layouts
+ m.template 'layout.rhtml', File.join( 'themes', file_name, 'layouts', 'default.rhtml' )
+ #m.template 'layout.liquid', File.join( 'themes', file_name, 'layouts', 'default.liquid' )
+ # view readme
+ m.template 'views_readme', File.join( 'themes', file_name, 'views', 'views_readme.txt' )
+ end
+ end
+end
\ No newline at end of file
diff --git a/init.rb b/init.rb
new file mode 100755
index 0000000..e5d87a9
--- /dev/null
+++ b/init.rb
@@ -0,0 +1,18 @@
+# Initializes theme support by extending some of the core Rails classes
+require 'patches/actionview_ex'
+require 'patches/actioncontroller_ex'
+require 'patches/actionmailer_ex'
+require 'patches/routeset_ex'
+
+# Add the tag helpers for rhtml and, optionally, liquid templates
+require 'helpers/rhtml_theme_tags'
+
+# Commented out to remove the message
+# "Liquid doesn't seem to be loaded... uninitialized constant Liquid"
+
+#begin
+# require 'helpers/liquid_theme_tags'
+#rescue
+# # I guess Liquid isn't being used...
+# STDERR.puts "Liquid doesn't seem to be loaded... #{$!}"
+#end
diff --git a/lib/helpers/liquid_theme_tags.rb b/lib/helpers/liquid_theme_tags.rb
new file mode 100755
index 0000000..51a30b0
--- /dev/null
+++ b/lib/helpers/liquid_theme_tags.rb
@@ -0,0 +1,31 @@
+# A Liquid Tag for retrieving path information for theme specific media
+#
+# Returns the path based on the file extension
+#
+class Themeitem < Liquid::Block
+
+ @@image_exts = %w( .png .jpg .jpeg .jpe .gif )
+ @@stylesheet_exts = %w( .css )
+ @@javascript_exts = %w( .js .htc )
+
+ def render(context)
+ # Which, if either, of these are correct?
+ base_url = context['request'].relative_url_root || ActionController::Base.asset_host.to_s
+ theme_name = @theme_name || context['active_theme']
+
+ filename = @nodelist.join('').strip
+ ext = File.extname( filename )
+
+ if @@image_exts.include?( ext )
+ "#{base_url}/themes/#{theme_name}/images/#{filename}"
+
+ elsif @@stylesheet_exts.include?( ext )
+ "#{base_url}/themes/#{theme_name}/stylesheets/#{filename}"
+
+ elsif @@javascript_exts.include?( ext )
+ "#{base_url}/themes/#{theme_name}/javascript/#{filename}"
+ end
+ end
+end
+
+Liquid::Template.register_tag( 'themeitem', Themeitem )
\ No newline at end of file
diff --git a/lib/helpers/rhtml_theme_tags.rb b/lib/helpers/rhtml_theme_tags.rb
new file mode 100755
index 0000000..bbd16f2
--- /dev/null
+++ b/lib/helpers/rhtml_theme_tags.rb
@@ -0,0 +1,66 @@
+#
+# These are theme helper tags
+#
+module ActionView::Helpers::AssetTagHelper
+
+ # returns the public path to a theme stylesheet
+ def theme_stylesheet_path( source=nil, theme=nil )
+ theme = theme || controller.current_theme
+ compute_public_path(source || "theme", "themes/#{theme}/stylesheets", 'css')
+ end
+
+ # returns the path to a theme image
+ def theme_image_path( source, theme=nil )
+ theme = theme || controller.current_theme
+ compute_public_path(source, "themes/#{theme}/images", 'png')
+ end
+
+ # returns the path to a theme javascript
+ def theme_javascript_path( source, theme=nil )
+ theme = theme || controller.current_theme
+ compute_public_path(source, "themes/#{theme}/javascript", 'js')
+ end
+
+
+ # This tag it will automatially include theme specific css files
+ def theme_stylesheet_link_tag(*sources)
+ sources.uniq!
+ options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { }
+ sources.collect { |source|
+ source = theme_stylesheet_path(source)
+ tag("link", { "rel" => "Stylesheet", "type" => "text/css", "media" => "screen", "href" => source }.merge(options))
+ }.join("\n")
+ end
+
+ # This tag will return a theme-specific IMG
+ def theme_image_tag(source, options = {})
+ options.symbolize_keys
+
+ options[:src] = theme_image_path(source)
+ options[:alt] ||= File.basename(options[:src], '.*').split('.').first.capitalize
+
+ if options[:size]
+ options[:width], options[:height] = options[:size].split("x")
+ options.delete :size
+ end
+
+ tag("img", options)
+ end
+
+ # This tag can be used to return theme-specific javscripts
+ def theme_javascript_include_tag(*sources)
+ options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { }
+ if sources.include?(:defaults)
+ sources = sources[0..(sources.index(:defaults))] +
+ @@javascript_default_sources.dup +
+ sources[(sources.index(:defaults) + 1)..sources.length]
+ sources.delete(:defaults)
+ sources << "application" if defined?(RAILS_ROOT) && File.exists?("#{RAILS_ROOT}/public/javascripts/application.js")
+ end
+ sources.collect { |source|
+ source = theme_javascript_path(source)
+ content_tag("script", "", { "type" => "text/javascript", "src" => source }.merge(options))
+ }.join("\n")
+ end
+
+end
\ No newline at end of file
diff --git a/lib/patches/actioncontroller_ex.rb b/lib/patches/actioncontroller_ex.rb
new file mode 100755
index 0000000..6cc9bc6
--- /dev/null
+++ b/lib/patches/actioncontroller_ex.rb
@@ -0,0 +1,59 @@
+# Extend the Base ActionController to support themes
+ActionController::Base.class_eval do
+
+ attr_accessor :current_theme
+ attr_accessor :force_liquid_template
+
+ # Use this in your controller just like the layout macro.
+ # Example:
+ #
+ # theme 'theme_name'
+ #
+ # -or-
+ #
+ # theme :get_theme
+ #
+ # def get_theme
+ # 'theme_name'
+ # end
+ def self.theme(theme_name, conditions = {})
+ # TODO: Allow conditions... (?)
+ write_inheritable_attribute "theme", theme_name
+ end
+
+ # Set force_liquid to true in your controlelr to only allow
+ # Liquid template in themes.
+ # Example:
+ #
+ # force_liquid true
+ def self.force_liquid(force_liquid_value, conditions = {})
+ # TODO: Allow conditions... (?)
+ write_inheritable_attribute "force_liquid", force_liquid_value
+ end
+
+ # Retrieves the current set theme
+ def current_theme(passed_theme=nil)
+ theme = passed_theme || self.class.read_inheritable_attribute("theme")
+
+ @active_theme = case theme
+ when Symbol then send(theme)
+ when Proc then theme.call(self)
+ when String then theme
+ end
+ end
+
+ # Retrieves the force liquid flag
+ def force_liquid_template(passed_value=nil)
+ force_liquid = passed_value || self.class.read_inheritable_attribute("force_liquid")
+
+ force_liquid_template = case force_liquid
+ when Symbol then send(force_liquid)
+ when Proc then force_liquid.call(self)
+ when String then force_liquid == 'true'
+ when TrueClass then force_liquid
+ when FalseClass then force_liquid
+ when Fixnum then force_liquid == 1
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/lib/patches/actionmailer_ex.rb b/lib/patches/actionmailer_ex.rb
new file mode 100755
index 0000000..c42db66
--- /dev/null
+++ b/lib/patches/actionmailer_ex.rb
@@ -0,0 +1,27 @@
+# Extend the Base ActionController to support themes
+ActionMailer::Base.class_eval do
+
+ alias_method :__render, :render
+ alias_method :__initialize, :initialize
+
+ @current_theme = nil
+
+ attr_reader :current_theme
+
+ def initialize(method_name=nil, *parameters)
+ if parameters[-1].is_a? Hash and (parameters[-1].include? :theme)
+ @current_theme = parameters[-1][:theme]
+ parameters[-1].delete :theme
+ parameters[-1][:current_theme] = @current_theme
+ end
+ create!(method_name, *parameters) if method_name
+ end
+
+ def render(opts)
+ body = opts.delete(:body)
+ body[:current_theme] = @current_theme
+ opts[:file] = "#{mailer_name}/#{opts[:file]}"
+ initialize_template_class(body).render(opts)
+ end
+
+end
\ No newline at end of file
diff --git a/lib/patches/actionview_ex.rb b/lib/patches/actionview_ex.rb
new file mode 100755
index 0000000..96c6992
--- /dev/null
+++ b/lib/patches/actionview_ex.rb
@@ -0,0 +1,45 @@
+# Extending ActionView::Base to support rendering themes
+#
+module ActionView
+
+ # Extending ActionView::Base to support rendering themes
+ class Base
+ alias_method :theme_support_old_render_file, :render_file
+ # Overrides the default Base#render_file to allow theme-specific views
+ def render_file(template_path, use_full_path = false, local_assigns = {})
+
+ search_path = [
+ "#{RAILS_ROOT}/themes/#{controller.current_theme}/views", # for components
+ "#{RAILS_ROOT}/themes/#{controller.current_theme}", # for layouts
+ ]
+
+ @finder.prepend_view_path(search_path)
+ local_assigns['active_theme'] = get_current_theme(local_assigns)
+ theme_support_old_render_file(template_path, use_full_path, local_assigns)
+
+ end
+ private
+
+ def force_liquid?
+ unless controller.nil?
+ if controller.respond_to?('force_liquid_template')
+ controller.force_liquid_template
+ end
+ else
+ false
+ end
+ end
+
+ def get_current_theme(local_assigns)
+ unless controller.nil?
+ if controller.respond_to?('current_theme')
+ return controller.current_theme || false
+ end
+ end
+ # Used with ActionMailers
+ if local_assigns.include? :current_theme
+ return local_assigns.delete :current_theme
+ end
+ end
+ end
+end
diff --git a/lib/patches/routeset_ex.rb b/lib/patches/routeset_ex.rb
new file mode 100755
index 0000000..9617f2d
--- /dev/null
+++ b/lib/patches/routeset_ex.rb
@@ -0,0 +1,26 @@
+# Extends ActionController::Routing::RouteSet to automatically add the theme routes
+class ActionController::Routing::RouteSet
+
+ alias_method :__draw, :draw
+
+ # Overrides the default RouteSet#draw to automatically
+ # include the routes needed by the ThemeController
+ def draw
+ clear!
+ map = Mapper.new(self)
+
+ create_theme_routes(map)
+ yield map
+
+ named_routes.install
+ end
+
+ # Creates the required routes for the ThemeController...
+ def create_theme_routes(map)
+ map.theme_images "/themes/:theme/images/*filename", :controller=>'theme', :action=>'images'
+ map.theme_stylesheets "/themes/:theme/stylesheets/*filename", :controller=>'theme', :action=>'stylesheets'
+ map.theme_javascript "/themes/:theme/javascript/*filename", :controller=>'theme', :action=>'javascript'
+ map.connect "/themes/*whatever", :controller=>'theme', :action=>'error'
+ end
+
+end
\ No newline at end of file
diff --git a/lib/theme.rb b/lib/theme.rb
new file mode 100755
index 0000000..4562784
--- /dev/null
+++ b/lib/theme.rb
@@ -0,0 +1,58 @@
+class Theme
+ cattr_accessor :cache_theme_lookup
+ @@cache_theme_lookup = false
+
+ attr_accessor :name, :title, :description, :preview_image
+
+ def initialize(name)
+ @name = name
+ @title = name.underscore.humanize.titleize
+ @description_html = nil
+ end
+
+ def description
+ if @description_html.nil?
+ @description_html = RedCloth.new(File.read( File.join(Theme.path_to_theme(name), "about.markdown") )).to_html(:markdown, :textile) rescue "#{title}"
+ end
+ @description_html
+ end
+
+ def has_preview?
+ File.exists?( File.join( Theme.path_to_theme(name), 'images', 'preview.png' ) ) rescue false
+ end
+
+ def preview_image
+ 'preview.png'
+ end
+
+ def self.find_all
+ installed_themes.inject([]) do |array, path|
+ array << theme_from_path(path)
+ end
+ end
+
+private
+
+ def self.themes_root
+ File.join(RAILS_ROOT, "themes")
+ end
+
+ def self.path_to_theme(theme)
+ File.join(themes_root, theme)
+ end
+
+ def self.theme_from_path(path)
+ name = path.scan(/[-\w]+$/i).flatten.first
+ self.new(name)
+ end
+
+ def self.installed_themes
+ cache_theme_lookup ? @theme_cache ||= search_theme_directory : search_theme_directory
+ end
+
+ def self.search_theme_directory
+ Dir.glob("#{themes_root}/[-_a-zA-Z0-9]*").collect do |file|
+ file if File.directory?(file)
+ end.compact
+ end
+end
diff --git a/lib/theme_controller.rb b/lib/theme_controller.rb
new file mode 100755
index 0000000..76d7ba2
--- /dev/null
+++ b/lib/theme_controller.rb
@@ -0,0 +1,61 @@
+# The controller for serving/cacheing theme content...
+#
+class ThemeController < ActionController::Base
+
+ after_filter :cache_theme_files
+
+ def stylesheets
+ render_theme_item(:stylesheets, params[:filename].to_s, params[:theme], 'text/css')
+ end
+
+ def javascript
+ render_theme_item(:javascript, params[:filename].to_s, params[:theme], 'text/javascript')
+ end
+
+ def images
+ render_theme_item(:images, params[:filename].to_s, params[:theme])
+ end
+
+ def error
+ render :nothing => true, :status => 404
+ end
+
+ private
+
+ def render_theme_item(type, file, theme, mime = mime_for(file))
+ render :text => "Not Found", :status => 404 and return if file.split(%r{[\\/]}).include?("..")
+ send_file "#{Theme.path_to_theme(theme)}/#{type}/#{file}", :type => mime, :disposition => 'inline', :stream => false
+ end
+
+ def cache_theme_files
+ path = request.request_uri
+ begin
+ ThemeController.cache_page( response.body, path )
+ rescue
+ STERR.puts "Cache Exception: #{$!}"
+ end
+ end
+
+
+ def mime_for(filename)
+ case filename.downcase
+ when /\.js$/
+ 'text/javascript'
+ when /\.css$/
+ 'text/css'
+ when /\.gif$/
+ 'image/gif'
+ when /(\.jpg|\.jpeg)$/
+ 'image/jpeg'
+ when /\.png$/
+ 'image/png'
+ when /\.swf$/
+ 'application/x-shockwave-flash'
+ else
+ 'application/binary'
+ end
+ end
+
+end
+
+
diff --git a/lib/theme_error.rb b/lib/theme_error.rb
new file mode 100755
index 0000000..85e4e3e
--- /dev/null
+++ b/lib/theme_error.rb
@@ -0,0 +1,4 @@
+# ThemeError is thrown when force_liquid is true, and
+# a .liquid template isn't found.
+class ThemeError < StandardError
+end
diff --git a/lib/theme_helper.rb b/lib/theme_helper.rb
new file mode 100755
index 0000000..61e429e
--- /dev/null
+++ b/lib/theme_helper.rb
@@ -0,0 +1,3 @@
+# this is here so that Rails doesn't complain about a missing default helper...
+module ThemeHelper
+end
\ No newline at end of file
diff --git a/tasks/themes.rake b/tasks/themes.rake
new file mode 100755
index 0000000..260dd68
--- /dev/null
+++ b/tasks/themes.rake
@@ -0,0 +1,23 @@
+
+desc "Creates the cached (public) theme folders"
+task :theme_create_cache do
+ for theme in Dir.glob("#{RAILS_ROOT}/themes/*")
+ theme_name = theme.split( File::Separator )[-1]
+ puts "Creating #{RAILS_ROOT}/public/themes/#{theme_name}"
+
+ FileUtils.mkdir_p "#{RAILS_ROOT}/public/themes/#{theme_name}"
+
+ FileUtils.cp_r "#{theme}/images", "#{RAILS_ROOT}/public/themes/#{theme_name}/images", :verbose => true
+ FileUtils.cp_r "#{theme}/stylesheets", "#{RAILS_ROOT}/public/themes/#{theme_name}/stylesheets", :verbose => true
+ FileUtils.cp_r "#{theme}/javascript", "#{RAILS_ROOT}/public/themes/#{theme_name}/javascript", :verbose => true
+ end
+end
+
+desc "Removes the cached (public) theme folders"
+task :theme_remove_cache do
+ puts "Removing #{RAILS_ROOT}/public/themes"
+ FileUtils.rm_r "#{RAILS_ROOT}/public/themes", :force => true
+end
+
+desc "Updates the cached (public) theme folders"
+task :theme_update_cache => [:theme_remove_cache, :theme_create_cache]
\ No newline at end of file