themes_for_rails4 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.rspec +2 -0
- data/.travis.yml +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +117 -0
- data/LICENSE +21 -0
- data/README.textile +53 -0
- data/Rakefile +11 -0
- data/doc/README.textile +380 -0
- data/doc/REVIEW_NOTES +0 -0
- data/doc/RMU_REVIEW +26 -0
- data/doc/TODO.textile +3 -0
- data/lib/generators/themes_for_rails/install_generator.rb +16 -0
- data/lib/generators/themes_for_rails/templates/theme/images/.gitkeep +0 -0
- data/lib/generators/themes_for_rails/templates/theme/javascripts/.gitkeep +0 -0
- data/lib/generators/themes_for_rails/templates/theme/stylesheets/.gitkeep +0 -0
- data/lib/generators/themes_for_rails/templates/theme/views/layouts/.gitkeep +0 -0
- data/lib/generators/themes_for_rails/theme_generator.rb +14 -0
- data/lib/tasks/themes_for_rails.rake +40 -0
- data/lib/themes_for_rails/action_controller.rb +32 -0
- data/lib/themes_for_rails/action_mailer.rb +22 -0
- data/lib/themes_for_rails/action_view.rb +66 -0
- data/lib/themes_for_rails/assets_controller.rb +68 -0
- data/lib/themes_for_rails/common_methods.rb +98 -0
- data/lib/themes_for_rails/config.rb +79 -0
- data/lib/themes_for_rails/digested_action_view.rb +64 -0
- data/lib/themes_for_rails/interpolation.rb +11 -0
- data/lib/themes_for_rails/railtie.rb +42 -0
- data/lib/themes_for_rails/routes.rb +30 -0
- data/lib/themes_for_rails/url_helpers.rb +27 -0
- data/lib/themes_for_rails/version.rb +4 -0
- data/lib/themes_for_rails.rb +73 -0
- data/test/dummy_app/.gitignore +4 -0
- data/test/dummy_app/Gemfile +30 -0
- data/test/dummy_app/Rakefile +7 -0
- data/test/dummy_app/another_themes/another_default/images/logo.png +0 -0
- data/test/dummy_app/another_themes/another_default/images/nested/logo.png +0 -0
- data/test/dummy_app/another_themes/another_default/javascripts/app.js +1 -0
- data/test/dummy_app/another_themes/another_default/stylesheets/style.css +0 -0
- data/test/dummy_app/another_themes/another_default/stylesheets/style2.css +3 -0
- data/test/dummy_app/another_themes/another_default/views/layouts/default.html.erb +10 -0
- data/test/dummy_app/another_themes/another_default/views/products/index.html.erb +0 -0
- data/test/dummy_app/app/controllers/application_controller.rb +3 -0
- data/test/dummy_app/app/helpers/application_helper.rb +2 -0
- data/test/dummy_app/app/views/layouts/application.html.erb +14 -0
- data/test/dummy_app/config/application.rb +42 -0
- data/test/dummy_app/config/boot.rb +13 -0
- data/test/dummy_app/config/database.yml +18 -0
- data/test/dummy_app/config/environment.rb +5 -0
- data/test/dummy_app/config/environments/development.rb +26 -0
- data/test/dummy_app/config/environments/production.rb +49 -0
- data/test/dummy_app/config/environments/test.rb +35 -0
- data/test/dummy_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy_app/config/initializers/inflections.rb +10 -0
- data/test/dummy_app/config/initializers/mime_types.rb +5 -0
- data/test/dummy_app/config/initializers/secret_token.rb +7 -0
- data/test/dummy_app/config/initializers/session_store.rb +8 -0
- data/test/dummy_app/config/locales/en.yml +5 -0
- data/test/dummy_app/config/routes.rb +4 -0
- data/test/dummy_app/config.ru +4 -0
- data/test/dummy_app/db/seeds.rb +7 -0
- data/test/dummy_app/empty_themes/.gitkeep +0 -0
- data/test/dummy_app/lib/tasks/.gitkeep +0 -0
- data/test/dummy_app/public/404.html +26 -0
- data/test/dummy_app/public/422.html +26 -0
- data/test/dummy_app/public/500.html +26 -0
- data/test/dummy_app/public/favicon.ico +0 -0
- data/test/dummy_app/public/images/rails.png +0 -0
- data/test/dummy_app/public/index.html +239 -0
- data/test/dummy_app/public/javascripts/application.js +2 -0
- data/test/dummy_app/public/javascripts/controls.js +965 -0
- data/test/dummy_app/public/javascripts/dragdrop.js +974 -0
- data/test/dummy_app/public/javascripts/effects.js +1123 -0
- data/test/dummy_app/public/javascripts/prototype.js +6001 -0
- data/test/dummy_app/public/javascripts/rails.js +175 -0
- data/test/dummy_app/public/robots.txt +5 -0
- data/test/dummy_app/public/stylesheets/.gitkeep +0 -0
- data/test/dummy_app/script/rails +6 -0
- data/test/dummy_app/themes/default/images/logo.png +0 -0
- data/test/dummy_app/themes/default/images/nested/logo.png +0 -0
- data/test/dummy_app/themes/default/javascripts/app.js +1 -0
- data/test/dummy_app/themes/default/javascripts/app.min.js +0 -0
- data/test/dummy_app/themes/default/stylesheets/images/logo.png +0 -0
- data/test/dummy_app/themes/default/stylesheets/style.css +0 -0
- data/test/dummy_app/themes/default/stylesheets/style2.css +3 -0
- data/test/dummy_app/themes/default/views/layouts/default.html.erb +10 -0
- data/test/dummy_app/themes/default/views/products/index.html.erb +0 -0
- data/test/lib/action_controller_test.rb +170 -0
- data/test/lib/action_mailer_test.rb +35 -0
- data/test/lib/action_view_test.rb +54 -0
- data/test/lib/assets_controller_test.rb +73 -0
- data/test/lib/common_methods_test.rb +28 -0
- data/test/lib/config_test.rb +26 -0
- data/test/lib/integration_test.rb +12 -0
- data/test/lib/routes_test.rb +40 -0
- data/test/lib/themes_for_rails_test.rb +18 -0
- data/test/support/extensions.rb +19 -0
- data/test/test_helper.rb +12 -0
- data/themes_for_rails.gemspec +25 -0
- metadata +280 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
namespace :themes do
|
|
2
|
+
desc "Creates the cached theme folder"
|
|
3
|
+
task :create_cache => :environment do
|
|
4
|
+
for theme in ThemesForRails.available_themes
|
|
5
|
+
theme_name = File.basename(theme)
|
|
6
|
+
theme_dir = ThemesForRails.config.themes_dir
|
|
7
|
+
theme_base = "#{Rails.public_path}/#{theme_dir}/#{theme_name}"
|
|
8
|
+
puts "Creating #{theme_base}"
|
|
9
|
+
|
|
10
|
+
FileUtils.mkdir_p "#{theme_base}"
|
|
11
|
+
FileUtils.cp_r Dir["#{theme}/{images,stylesheets,javascripts}"], theme_base, :verbose => true
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
desc "Removes the cached (public) theme folders"
|
|
15
|
+
task :remove_cache => :environment do
|
|
16
|
+
theme_dir = ThemesForRails.config.themes_dir
|
|
17
|
+
puts "Removing #{Rails.public_path}/#{theme_dir}"
|
|
18
|
+
FileUtils.rm_r "#{Rails.public_path}/#{theme_dir}", :force => true
|
|
19
|
+
end
|
|
20
|
+
desc "Updates the cached (public) theme folders"
|
|
21
|
+
task :update_cache => [:remove_cache, :create_cache]
|
|
22
|
+
|
|
23
|
+
desc "Add theme view paths to ActionView PathSet"
|
|
24
|
+
task :add_theme_to_view_paths => :environment do
|
|
25
|
+
raise 'you must provide THEME for theme support to work' unless theme = ENV['THEME']
|
|
26
|
+
puts "adding theme [#{theme}] to view path"
|
|
27
|
+
require 'themes_for_rails/common_methods'
|
|
28
|
+
include ThemesForRails::CommonMethods
|
|
29
|
+
|
|
30
|
+
theme_view_path=theme_view_path_for(theme)
|
|
31
|
+
ActionController::Base.view_paths.paths.prepend(theme_view_path) if theme
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
namespace :cache_digests do
|
|
36
|
+
puts "patching cache_digests with themes_for_rails support"
|
|
37
|
+
# Add themes support to cache_digest gem rake tasks
|
|
38
|
+
task :nested_dependencies => ['themes:add_theme_to_view_paths']
|
|
39
|
+
task :dependencies => ['themes:add_theme_to_view_paths']
|
|
40
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module ThemesForRails
|
|
3
|
+
|
|
4
|
+
module ActionController
|
|
5
|
+
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
|
|
10
|
+
include ThemesForRails::CommonMethods
|
|
11
|
+
include ThemesForRails::UrlHelpers
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module ClassMethods
|
|
16
|
+
|
|
17
|
+
def theme(name, options = {})
|
|
18
|
+
before_filter(options) do |controller|
|
|
19
|
+
controller.set_theme(name)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def theme(name)
|
|
26
|
+
set_theme(name)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module ThemesForRails
|
|
3
|
+
|
|
4
|
+
module ActionMailer
|
|
5
|
+
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
include ThemesForRails::ActionController
|
|
10
|
+
alias_method_chain :mail, :theme
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def mail_with_theme(headers = {}, &block)
|
|
14
|
+
theme_opts = headers[:theme] || headers['X-theme'] || self.class.default[:theme]
|
|
15
|
+
theme(theme_opts) if theme_opts
|
|
16
|
+
|
|
17
|
+
mail_without_theme(headers, &block)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module ThemesForRails
|
|
3
|
+
|
|
4
|
+
module ActionView
|
|
5
|
+
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
include ThemesForRails::CommonMethods
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def current_theme_stylesheet_path(asset)
|
|
13
|
+
base_theme_stylesheet_path(:theme => self.theme_name, :asset => digest_for_stylesheet("#{asset}.css", self.theme_name))
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def current_theme_javascript_path(asset)
|
|
17
|
+
base_theme_javascript_path(:theme => self.theme_name, :asset => digest_for_javascript("#{asset}.js", self.theme_name))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def current_theme_image_path(asset)
|
|
21
|
+
image, extension = name_ext(asset)
|
|
22
|
+
base_theme_image_path(:theme => self.theme_name, :asset => digest_for_image("#{image}.#{extension}", self.theme_name))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def theme_stylesheet_path(asset, new_theme_name = self.theme_name)
|
|
26
|
+
base_theme_stylesheet_path(:theme => new_theme_name, :asset => digest_for_stylesheet("#{asset}.css", new_theme_name))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def theme_javascript_path(asset, new_theme_name = self.theme_name)
|
|
30
|
+
base_theme_javascript_path(:theme => new_theme_name, :asset => digest_for_javascript("#{asset}.js", new_theme_name))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def theme_image_path(asset, new_theme_name = self.theme_name)
|
|
34
|
+
image, extension = name_ext(asset)
|
|
35
|
+
base_theme_image_path(:theme => new_theme_name, :asset => digest_for_image("#{image}.#{extension}", new_theme_name))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def theme_image_tag(source, options = {})
|
|
39
|
+
image, extension = name_ext(source)
|
|
40
|
+
image_tag(theme_image_path(digest_for_image("#{image}.#{extension}", self.theme_name)), options)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def theme_image_submit_tag(source, options = {})
|
|
44
|
+
image, extension = name_ext(source)
|
|
45
|
+
image_submit_tag(theme_image_path(digest_for_image("#{image}.#{extension}", self.theme_name)), options)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def theme_javascript_include_tag(*files)
|
|
49
|
+
options = files.extract_options!
|
|
50
|
+
options.merge!({ :type => "text/javascript" })
|
|
51
|
+
files_with_options = files.collect {|file| theme_javascript_path(file) }
|
|
52
|
+
files_with_options += [options]
|
|
53
|
+
|
|
54
|
+
javascript_include_tag(*files_with_options)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def theme_stylesheet_link_tag(*files)
|
|
58
|
+
options = files.extract_options!
|
|
59
|
+
options.merge!({ :type => "text/css" })
|
|
60
|
+
files_with_options = files.collect {|file| theme_stylesheet_path(file) }
|
|
61
|
+
files_with_options += [options]
|
|
62
|
+
|
|
63
|
+
stylesheet_link_tag(*files_with_options)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require "action_controller/metal"
|
|
3
|
+
|
|
4
|
+
module ThemesForRails
|
|
5
|
+
class AssetsController < ActionController::Base
|
|
6
|
+
|
|
7
|
+
def stylesheets
|
|
8
|
+
handle_asset("stylesheets")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def javascripts
|
|
12
|
+
handle_asset("javascripts")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def images
|
|
16
|
+
handle_asset("images")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def handle_asset(prefix)
|
|
22
|
+
asset, theme = params[:asset], params[:theme]
|
|
23
|
+
find_themed_asset(asset, theme, prefix) do |path, mime_type|
|
|
24
|
+
response.headers['ETag'] = %("#{Digest::MD5.hexdigest(ActiveSupport::Cache.expand_cache_key(File.mtime(path).to_s + path))}")
|
|
25
|
+
response.headers['Cache-Control'] = "public, max-age=2592000"
|
|
26
|
+
send_file path, :type => mime_type, :disposition => "inline"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def find_themed_asset(asset_name, asset_theme, asset_type, &block)
|
|
31
|
+
path = asset_path(asset_name, asset_theme, asset_type)
|
|
32
|
+
if File.exists?(path)
|
|
33
|
+
yield path, mime_type_for(request)
|
|
34
|
+
elsif File.extname(path).blank?
|
|
35
|
+
asset_name = "#{asset_name}.#{extension_from(request.path_info)}"
|
|
36
|
+
return find_themed_asset(asset_name, asset_theme, asset_type, &block)
|
|
37
|
+
else
|
|
38
|
+
render_not_found
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def asset_path(asset_name, asset_theme, asset_type)
|
|
43
|
+
File.join(theme_asset_path_for(asset_theme), asset_type, asset_name)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def render_not_found
|
|
47
|
+
render :text => 'Not found', :status => 404
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def mime_type_for(request)
|
|
51
|
+
existing_mime_type = mime_type_from_uri(request.path_info)
|
|
52
|
+
unless existing_mime_type.nil?
|
|
53
|
+
existing_mime_type.to_s
|
|
54
|
+
else
|
|
55
|
+
"image/#{extension_from(request.path_info)}"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def mime_type_from_uri(path)
|
|
60
|
+
extension = extension_from(path)
|
|
61
|
+
Mime::Type.lookup_by_extension(extension)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def extension_from(path)
|
|
65
|
+
File.extname(path).to_s[1..-1]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module ThemesForRails
|
|
3
|
+
module CommonMethods
|
|
4
|
+
|
|
5
|
+
include ThemesForRails::Interpolation
|
|
6
|
+
|
|
7
|
+
def theme_name
|
|
8
|
+
@cached_theme_name ||= begin
|
|
9
|
+
case @theme_name
|
|
10
|
+
when Symbol then
|
|
11
|
+
self.respond_to?(@theme_name, true) ? self.send(@theme_name) : @theme_name.to_s
|
|
12
|
+
when String then @theme_name
|
|
13
|
+
else
|
|
14
|
+
nil
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def theme_name=(name)
|
|
20
|
+
@theme_name = name
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def set_theme(name)
|
|
24
|
+
self.theme_name = name
|
|
25
|
+
if valid_theme?
|
|
26
|
+
add_theme_view_path
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
public
|
|
31
|
+
|
|
32
|
+
def valid_theme?
|
|
33
|
+
!self.theme_name.nil?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# will add the view path for the current theme
|
|
37
|
+
def add_theme_view_path
|
|
38
|
+
add_theme_view_path_for(self.theme_name)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# will add the view path for a given theme name
|
|
42
|
+
def add_theme_view_path_for(name)
|
|
43
|
+
self.view_paths.insert 0, ::ActionView::FileSystemResolver.new(theme_view_path_for(name))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def digest_for_image(asset, theme_context)
|
|
47
|
+
if ThemesForRails.config.asset_digests_enabled?
|
|
48
|
+
asset_paths.digest_for("#{theme_context}/images/#{asset}") || asset
|
|
49
|
+
else
|
|
50
|
+
asset
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def digest_for_javascript(asset, theme_context)
|
|
55
|
+
if ThemesForRails.config.asset_digests_enabled?
|
|
56
|
+
asset_paths.digest_for("#{theme_context}/javascripts/#{asset}") || asset
|
|
57
|
+
else
|
|
58
|
+
asset
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def digest_for_stylesheet(asset, theme_context)
|
|
63
|
+
if ThemesForRails.config.asset_digests_enabled?
|
|
64
|
+
#Rails.application.config.assets.digests["#{theme_context}/stylesheets/#{asset}"] || asset
|
|
65
|
+
asset_paths.digest_for("#{theme_context}/stylesheets/#{asset}") || asset
|
|
66
|
+
else
|
|
67
|
+
asset
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def name_ext(file_name)
|
|
72
|
+
ext = File.extname(file_name)
|
|
73
|
+
name = File.basename(file_name, ext)
|
|
74
|
+
ext.slice!(0) if ext.length > 0
|
|
75
|
+
return name, ext
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def public_theme_path
|
|
79
|
+
theme_view_path("/")
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def theme_asset_path
|
|
83
|
+
theme_asset_path_for(theme_name)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def theme_view_path
|
|
87
|
+
theme_view_path_for(theme_name)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def theme_view_path_for(theme_name)
|
|
91
|
+
interpolate(ThemesForRails.config.views_dir, theme_name)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def theme_asset_path_for(theme_name)
|
|
95
|
+
interpolate(ThemesForRails.config.assets_dir, theme_name)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module ThemesForRails
|
|
3
|
+
class Config
|
|
4
|
+
|
|
5
|
+
attr_writer :base_dir, :themes_dir, :assets_dir, :views_dir, :themes_routes_dir
|
|
6
|
+
attr_accessor :use_sass, :default_theme, :asset_digests_enabled
|
|
7
|
+
|
|
8
|
+
include Interpolation
|
|
9
|
+
|
|
10
|
+
def initialize(&block)
|
|
11
|
+
@use_sass = true
|
|
12
|
+
@default_theme = 'default'
|
|
13
|
+
@asset_digests_enabled = nil
|
|
14
|
+
yield if block_given?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def base_dir
|
|
18
|
+
@base_dir ||= Rails.root.to_s
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# relative assets dir for view overloading support
|
|
22
|
+
# used for theme_view_path_for method to get theme path and add to view paths.
|
|
23
|
+
# Defaults to themes_dir for non asset pipeline users
|
|
24
|
+
#
|
|
25
|
+
# If you are using the Rails Asset Pipeline, this should be changed to the
|
|
26
|
+
# path of your assets in your app. For example, if you store your themes
|
|
27
|
+
# under /app/assets/themes - {Rails.root}/app/assets/themes
|
|
28
|
+
# you would need to set this to 'app/assets/themes' in your initializer config
|
|
29
|
+
def assets_dir
|
|
30
|
+
@assets_dir ||= ":root/themes/:name"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# relative views directory for theme views to be separated from assets
|
|
34
|
+
# used for Asset Pipeline support. Defaults to match {assets_dir}/views
|
|
35
|
+
def views_dir
|
|
36
|
+
@views_dir ||= ":root/themes/:name/views"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def themes_dir
|
|
40
|
+
@themes_dir ||= ":root/themes"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Full path to themes
|
|
44
|
+
def themes_path
|
|
45
|
+
interpolate(themes_dir)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# This is the base themes dir that is used for mapping URL paths.
|
|
49
|
+
#
|
|
50
|
+
# If you are using the Rails Asset Pipeline, this should be changed to the
|
|
51
|
+
# prefix dir of your assets path. For example, if you store your themes
|
|
52
|
+
# under /app/assets/themes - {Rails.root}/app/assets/themes
|
|
53
|
+
# you would need to set this value to 'assets' to match up with the Sprockets
|
|
54
|
+
# path resolution process.
|
|
55
|
+
|
|
56
|
+
def themes_routes_dir
|
|
57
|
+
@themes_routes_dir ||= "themes"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def clear
|
|
61
|
+
@base_dir = nil
|
|
62
|
+
@themes_dir = nil
|
|
63
|
+
@assets_dir = nil
|
|
64
|
+
@views_dir = nil
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def use_sass?
|
|
68
|
+
@use_sass and sass_is_available?
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def sass_is_available?
|
|
72
|
+
!!defined?Sass::Plugin
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def asset_digests_enabled?
|
|
76
|
+
@asset_digests_enabled
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module ThemesForRails
|
|
3
|
+
|
|
4
|
+
module DigestedActionView
|
|
5
|
+
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
include ThemesForRails::CommonMethods
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def current_theme_stylesheet_path(asset)
|
|
13
|
+
digest_for_stylesheet("#{asset}.css", self.theme_name)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def current_theme_javascript_path(asset)
|
|
17
|
+
digest_for_javascript("#{asset}.js", self.theme_name)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def current_theme_image_path(asset)
|
|
21
|
+
image, extension = name_ext(asset)
|
|
22
|
+
digest_for_image("#{image}.#{extension}", self.theme_name)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def theme_stylesheet_path(asset, new_theme_name = self.theme_name)
|
|
26
|
+
digest_for_stylesheet("#{asset}.css", new_theme_name)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def theme_javascript_path(asset, new_theme_name = self.theme_name)
|
|
30
|
+
digest_for_javascript("#{asset}.js", new_theme_name)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def theme_image_path(asset, new_theme_name = self.theme_name)
|
|
34
|
+
path_to_image(digest_for_image(asset, new_theme_name))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def theme_image_tag(source, options = {})
|
|
38
|
+
image_tag(theme_image_path("#{source}", self.theme_name), options)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def theme_image_submit_tag(source, options = {})
|
|
42
|
+
image, extension = name_ext(source)
|
|
43
|
+
image_submit_tag(theme_image_path("#{image}.#{extension}", self.theme_name), options)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def theme_javascript_include_tag(*files)
|
|
47
|
+
options = files.extract_options!
|
|
48
|
+
options.merge!({ :type => "text/javascript" })
|
|
49
|
+
files_with_options = files.collect {|file| theme_javascript_path(file) }
|
|
50
|
+
files_with_options += [options]
|
|
51
|
+
|
|
52
|
+
javascript_include_tag(*files_with_options)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def theme_stylesheet_link_tag(*files)
|
|
56
|
+
options = files.extract_options!
|
|
57
|
+
options.merge!({ :type => "text/css" })
|
|
58
|
+
files_with_options = files.collect {|file| theme_stylesheet_path(file) }
|
|
59
|
+
files_with_options += [options]
|
|
60
|
+
|
|
61
|
+
stylesheet_link_tag(*files_with_options)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module ThemesForRails
|
|
3
|
+
class Railtie < ::Rails::Railtie
|
|
4
|
+
|
|
5
|
+
config.themes_for_rails = ActiveSupport::OrderedOptions.new
|
|
6
|
+
|
|
7
|
+
config.to_prepare do
|
|
8
|
+
ThemesForRails::Railtie.config.themes_for_rails.each do |key, value|
|
|
9
|
+
ThemesForRails.config.send "#{key}=".to_sym, value
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Adding theme stylesheets path to sass, automatically.
|
|
13
|
+
ThemesForRails.add_themes_path_to_sass if ThemesForRails.config.use_sass?
|
|
14
|
+
|
|
15
|
+
# Check if asset pipeline enabled
|
|
16
|
+
ThemesForRails.check_asset_pipeline
|
|
17
|
+
|
|
18
|
+
# Adding theme assets to the asset pipeline, automatically.
|
|
19
|
+
ThemesForRails.add_themes_assets_to_asset_pipeline if ThemesForRails.config.asset_digests_enabled?
|
|
20
|
+
|
|
21
|
+
ActiveSupport.on_load(:action_view) do
|
|
22
|
+
include ThemesForRails::ActionView
|
|
23
|
+
if ThemesForRails.config.asset_digests_enabled?
|
|
24
|
+
require 'themes_for_rails/digested_action_view'
|
|
25
|
+
include ThemesForRails::DigestedActionView
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
ActiveSupport.on_load(:action_controller) do
|
|
30
|
+
include ThemesForRails::ActionController
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
ActiveSupport.on_load(:action_mailer) do
|
|
34
|
+
include ThemesForRails::ActionMailer
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
rake_tasks do
|
|
39
|
+
load "tasks/themes_for_rails.rake"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module ThemesForRails
|
|
3
|
+
module Routes
|
|
4
|
+
|
|
5
|
+
def themes_for_rails
|
|
6
|
+
theme_dir = ThemesForRails.config.themes_routes_dir
|
|
7
|
+
constraints = { :theme => /[\w\.]*/ }
|
|
8
|
+
|
|
9
|
+
# Lets not pollute the routes if they aren't being used.
|
|
10
|
+
unless ThemesForRails.config.asset_digests_enabled?
|
|
11
|
+
get "#{theme_dir}/:theme/stylesheets/*asset" => 'themes_for_rails/assets#stylesheets',
|
|
12
|
+
:as => :base_theme_stylesheet, :constraints => constraints
|
|
13
|
+
get "#{theme_dir}/:theme/javascripts/*asset" => 'themes_for_rails/assets#javascripts',
|
|
14
|
+
:as => :base_theme_javascript, :constraints => constraints
|
|
15
|
+
get "#{theme_dir}/:theme/images/*asset" => 'themes_for_rails/assets#images',
|
|
16
|
+
:as => :base_theme_image, :constraints => constraints
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module ActionDispatch::Routing
|
|
24
|
+
class Mapper #:nodoc:
|
|
25
|
+
|
|
26
|
+
include ThemesForRails::Routes
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module ThemesForRails
|
|
3
|
+
module UrlHelpers
|
|
4
|
+
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
helper_method :current_theme_stylesheet_path,
|
|
9
|
+
:current_theme_javascript_path,
|
|
10
|
+
:current_theme_image_path
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def current_theme_stylesheet_path(asset)
|
|
14
|
+
base_theme_stylesheet_path(:theme => self.theme_name, :asset => digest_for_stylesheet("#{asset}.css", self.theme_name))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def current_theme_javascript_path(asset)
|
|
18
|
+
base_theme_javascript_path(:theme => self.theme_name, :asset => digest_for_javascript("#{asset}.js", self.theme_name))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def current_theme_image_path(asset)
|
|
22
|
+
image, extension = name_ext(asset)
|
|
23
|
+
base_theme_image_path(:theme => self.theme_name, :asset => digest_for_image("#{image}.#{extension}", self.theme_name))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module ThemesForRails
|
|
3
|
+
|
|
4
|
+
class << self
|
|
5
|
+
|
|
6
|
+
def config
|
|
7
|
+
@config ||= ThemesForRails::Config.new
|
|
8
|
+
yield(@config) if block_given?
|
|
9
|
+
@config
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def available_themes(&block)
|
|
13
|
+
Dir.glob(File.join(config.themes_path, "*"), &block)
|
|
14
|
+
end
|
|
15
|
+
alias each_theme_dir available_themes
|
|
16
|
+
|
|
17
|
+
def available_theme_names
|
|
18
|
+
available_themes.map {|theme| File.basename(theme) }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def add_themes_path_to_sass
|
|
22
|
+
if ThemesForRails.config.sass_is_available?
|
|
23
|
+
each_theme_dir do |dir|
|
|
24
|
+
if File.directory?(dir) # Need to get rid of the '.' and '..'
|
|
25
|
+
|
|
26
|
+
sass_dir = "#{dir}/stylesheets/sass"
|
|
27
|
+
css_dir = "#{dir}/stylesheets"
|
|
28
|
+
|
|
29
|
+
unless already_configured_in_sass?(sass_dir)
|
|
30
|
+
Sass::Plugin.add_template_location sass_dir, css_dir
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
else
|
|
35
|
+
raise "Sass is not available. What are you trying to do?"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def check_asset_pipeline
|
|
40
|
+
config.asset_digests_enabled ||= Rails.application.config.respond_to?(:assets) && Rails.application.config.assets.digest == true
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def add_themes_assets_to_asset_pipeline
|
|
44
|
+
Rails.logger.info "Start adding themes to assets [#{ThemesForRails.config.asset_digests_enabled?}]"
|
|
45
|
+
if ThemesForRails.config.asset_digests_enabled?
|
|
46
|
+
available_theme_names.each do |theme_name|
|
|
47
|
+
theme_asset_path = ThemesForRails.config.assets_dir.gsub(":root", ThemesForRails.config.base_dir).gsub(":name", theme_name.to_s)
|
|
48
|
+
Rails.logger.info "== Adding theme [#{theme_name}] asset dir [#{theme_asset_path}] to asset pipeline"
|
|
49
|
+
Rails.application.config.assets.paths.prepend(theme_asset_path) unless Rails.application.config.assets.paths.include?(theme_asset_path)
|
|
50
|
+
end unless ThemesForRails.config.base_dir =~ %r!/app/assets/!
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def already_configured_in_sass?(sass_dir)
|
|
55
|
+
Sass::Plugin.template_location_array.map(&:first).include?(sass_dir)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
require 'active_support/dependencies'
|
|
62
|
+
require 'themes_for_rails/interpolation'
|
|
63
|
+
require 'themes_for_rails/config'
|
|
64
|
+
require 'themes_for_rails/common_methods'
|
|
65
|
+
require 'themes_for_rails/url_helpers'
|
|
66
|
+
|
|
67
|
+
require 'themes_for_rails/action_view'
|
|
68
|
+
require 'themes_for_rails/assets_controller'
|
|
69
|
+
require 'themes_for_rails/action_controller'
|
|
70
|
+
require 'themes_for_rails/action_mailer'
|
|
71
|
+
require 'themes_for_rails/railtie'
|
|
72
|
+
require 'themes_for_rails/routes'
|
|
73
|
+
|