theme_generator 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/USAGE +21 -0
- data/templates/README +55 -0
- data/templates/about.markdown +3 -0
- data/templates/actioncontroller_ex.rb +45 -0
- data/templates/actionview_ex.rb +21 -0
- data/templates/init.rb +6 -0
- data/templates/layout.rhtml +11 -0
- data/templates/preview.png +0 -0
- data/templates/routeset_ex.rb +22 -0
- data/templates/theme.css +5 -0
- data/templates/theme.rb +59 -0
- data/templates/theme_controller.rb +59 -0
- data/templates/theme_helpers.rb +69 -0
- data/theme_generator.rb +37 -0
- metadata +62 -0
data/USAGE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
NAME
|
2
|
+
theme - Initializes the application to support themes and creates a new theme
|
3
|
+
folder structure.
|
4
|
+
|
5
|
+
SYNOPSIS
|
6
|
+
theme [theme name]
|
7
|
+
|
8
|
+
DESCRIPTION
|
9
|
+
This generator creates general purpose theme support. It's designed to leverage
|
10
|
+
webservers for the static content of the theme (images, stylesheets, javascripts,
|
11
|
+
etc).
|
12
|
+
|
13
|
+
Included:
|
14
|
+
- Abstraction of Typo style theme support
|
15
|
+
- New View Tag Helpers for accessing themed content
|
16
|
+
|
17
|
+
EXAMPLE
|
18
|
+
./script/generate theme default
|
19
|
+
|
20
|
+
This will generate the file structure for a theme named 'default' and prepare
|
21
|
+
the rails application for theme support.
|
data/templates/README
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
== Usage
|
2
|
+
|
3
|
+
You can specify the current theme the same way you would a layout:
|
4
|
+
|
5
|
+
class ApplicationController < ActionController::Base
|
6
|
+
|
7
|
+
layout 'default'
|
8
|
+
theme 'blue'
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
If your application supports per-user themes, and the user's selected theme is
|
13
|
+
stored in the user object, you could implement that like this:
|
14
|
+
|
15
|
+
class ApplicationController < ActionController::Base
|
16
|
+
|
17
|
+
layout 'default'
|
18
|
+
theme :get_user_theme
|
19
|
+
|
20
|
+
# If a user is logged in, use their theme choice, otherwise
|
21
|
+
# use the theme named 'default'
|
22
|
+
def get_user_theme
|
23
|
+
return @session[:user].theme unless @session[:user].nil?
|
24
|
+
'default'
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
In the views, there are theme specific helper tags available to you.
|
30
|
+
|
31
|
+
- theme_image_tag
|
32
|
+
- theme_image_path
|
33
|
+
- theme_javascript_include_tag
|
34
|
+
- theme_javascript_path
|
35
|
+
- theme_stylesheet_link_tag
|
36
|
+
- theme_stylesheet_path
|
37
|
+
|
38
|
+
|
39
|
+
== In the future...
|
40
|
+
|
41
|
+
- Add a rake task to pre-cache all static theme files (stylesheets, images, and javascript)
|
42
|
+
- Add a rake task to remove all cached theme files
|
43
|
+
|
44
|
+
|
45
|
+
== Changelog
|
46
|
+
|
47
|
+
1.0.0 - Initial release
|
48
|
+
1.0.1 - Added 'themes' directory, theme definition file, and symlinks
|
49
|
+
to the appropriate directories on supported platforms.
|
50
|
+
1.0.2 - The current_theme is now retrieved from the controller. Where
|
51
|
+
symlinks are created on *nix systems, shortcuts are created
|
52
|
+
on Windows if Win32Utils is installed.
|
53
|
+
1.1.0 - [Breaking] Abstraction of the Typo theme system. The themes are
|
54
|
+
now the same as is used in Typo. The theme engine itself is a
|
55
|
+
combination of plugins and a component.
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Extend the Base ActionController to support themes
|
2
|
+
#
|
3
|
+
ActionController::Base.class_eval do
|
4
|
+
|
5
|
+
attr_accessor :current_theme
|
6
|
+
|
7
|
+
def self.theme(theme_name, conditions = {})
|
8
|
+
# TODO: Allow conditions... (?)
|
9
|
+
write_inheritable_attribute "theme", theme_name
|
10
|
+
end
|
11
|
+
|
12
|
+
# You need to override this in your +ApplicationController+
|
13
|
+
# This should return the current theme name
|
14
|
+
def current_theme(passed_theme=nil)
|
15
|
+
theme = passed_theme || self.class.read_inheritable_attribute("theme")
|
16
|
+
|
17
|
+
active_theme = case theme
|
18
|
+
when Symbol then send(theme)
|
19
|
+
when Proc then theme.call(self)
|
20
|
+
when String then theme
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
alias_method :__active_layout, :active_layout
|
27
|
+
|
28
|
+
def active_layout(passed_layout = nil)
|
29
|
+
unless current_theme.nil?
|
30
|
+
puts "THEME LAYOUT"
|
31
|
+
layout = passed_layout || self.class.read_inheritable_attribute("layout")
|
32
|
+
|
33
|
+
active_layout = case layout
|
34
|
+
when Symbol then send(layout)
|
35
|
+
when Proc then layout.call(self)
|
36
|
+
when String then layout
|
37
|
+
end
|
38
|
+
|
39
|
+
active_layout.include?("/") ? active_layout : Theme.new(current_theme).layout(active_layout) if active_layout
|
40
|
+
else
|
41
|
+
__active_layout(passed_layout)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ActionView
|
2
|
+
class Base
|
3
|
+
alias_method :__render_file, :render_file
|
4
|
+
|
5
|
+
def render_file(template_path, use_full_path = true, local_assigns = {})
|
6
|
+
if use_full_path
|
7
|
+
begin
|
8
|
+
theme_path = "../../themes/#{controller.current_theme}/views/#{template_path}"
|
9
|
+
template_extension = pick_template_extension(theme_path)
|
10
|
+
__render_file(theme_path, use_full_path, local_assigns)
|
11
|
+
rescue => err
|
12
|
+
__render_file(template_path, use_full_path, local_assigns)
|
13
|
+
end
|
14
|
+
else
|
15
|
+
__render_file(template_path, use_full_path, local_assigns)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
end
|
data/templates/init.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
<html>
|
4
|
+
<head>
|
5
|
+
<title></title>
|
6
|
+
<%%= theme_stylesheet_link_tag %>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<%%= @content_for_layout %>
|
10
|
+
</body>
|
11
|
+
</html>
|
Binary file
|
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
class ActionController::Routing::RouteSet
|
3
|
+
|
4
|
+
alias_method :__reload, :reload
|
5
|
+
|
6
|
+
def reload
|
7
|
+
__reload
|
8
|
+
create_theme_routes
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_theme_routes
|
12
|
+
named_route 'theme_images', "/themes/:theme/images/:filename", :controller=>'theme_system/theme', :action=>'images'
|
13
|
+
named_route 'theme_stylesheets', "/themes/:theme/stylesheets/:filename", :controller=>'theme_system/theme', :action=>'stylesheets'
|
14
|
+
named_route 'theme_javascript', "/themes/:theme/javascript/:filename", :controller=>'theme_system/theme', :action=>'javascript'
|
15
|
+
|
16
|
+
connect "/themes/*", :controller=>'theme_system/theme', :action=>'error'
|
17
|
+
|
18
|
+
write_generation
|
19
|
+
write_recognition
|
20
|
+
ActionController::Routing::NamedRoutes.install
|
21
|
+
end
|
22
|
+
end
|
data/templates/theme.css
ADDED
data/templates/theme.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
class Theme
|
2
|
+
cattr_accessor :cache_theme_lookup
|
3
|
+
@@cache_theme_lookup = false
|
4
|
+
|
5
|
+
attr_accessor :name, :path, :description_html
|
6
|
+
|
7
|
+
def initialize(name, path=nil)
|
8
|
+
@name = name
|
9
|
+
@path = path ||= Theme.path_to_theme(name)
|
10
|
+
end
|
11
|
+
|
12
|
+
def layout(layout='default')
|
13
|
+
"../../themes/#{name}/layouts/#{layout}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def description
|
17
|
+
File.read("#{path}/about.markdown") rescue "### #{name}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.themes_root
|
21
|
+
RAILS_ROOT + "/themes"
|
22
|
+
end
|
23
|
+
|
24
|
+
# DEPRECATED: There is no 'current' theme, at least, not from here...
|
25
|
+
def self.current_theme_path
|
26
|
+
raise 'DEPRECATED: The current theme is set in the controller'
|
27
|
+
"#{themes_root}/#{config[:theme]}"
|
28
|
+
end
|
29
|
+
# DEPRECATED: There is no 'current' theme, at least, not from here...
|
30
|
+
def self.current
|
31
|
+
theme_from_path(current_theme_path)
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def self.path_to_theme(theme)
|
36
|
+
"#{themes_root}/#{theme}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.theme_from_path(path)
|
40
|
+
name = path.scan(/[-\w]+$/i).flatten.first
|
41
|
+
self.new(name, path)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.find_all
|
45
|
+
installed_themes.inject([]) do |array, path|
|
46
|
+
array << theme_from_path(path)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.installed_themes
|
51
|
+
cache_theme_lookup ? @theme_cache ||= search_theme_directory : search_theme_directory
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.search_theme_directory
|
55
|
+
Dir.glob("#{themes_root}/[-_a-zA-Z0-9]*").collect do |file|
|
56
|
+
file if File.directory?(file)
|
57
|
+
end.compact
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class ThemeSystem::ThemeController < ActionController::Base
|
2
|
+
|
3
|
+
after_filter :cache_theme_files
|
4
|
+
|
5
|
+
def stylesheets
|
6
|
+
render_theme_item(:stylesheets, params[:filename], params[:theme], 'text/css')
|
7
|
+
end
|
8
|
+
|
9
|
+
def javascript
|
10
|
+
render_theme_item(:javascript, params[:filename], params[:theme], 'text/javascript')
|
11
|
+
end
|
12
|
+
|
13
|
+
def images
|
14
|
+
render_theme_item(:images, params[:filename], params[:theme])
|
15
|
+
end
|
16
|
+
|
17
|
+
def error
|
18
|
+
render :nothing => true, :status => 404
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def render_theme_item(type, file, theme, mime = mime_for(file))
|
24
|
+
render :text => "Not Found", :status => 404 and return if file.split(%r{[\\/]}).include?("..")
|
25
|
+
send_file "#{Theme.path_to_theme(theme)}/#{type}/#{file}", :type => mime, :disposition => 'inline', :stream => false
|
26
|
+
end
|
27
|
+
|
28
|
+
def cache_theme_files
|
29
|
+
path = request.request_uri
|
30
|
+
begin
|
31
|
+
ThemeSystem::ThemeController.cache_page( response.body, path )
|
32
|
+
rescue
|
33
|
+
#STERR.puts "Cache Exception: #{$!}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def mime_for(filename)
|
39
|
+
case filename.downcase
|
40
|
+
when /\.js$/
|
41
|
+
'text/javascript'
|
42
|
+
when /\.css$/
|
43
|
+
'text/css'
|
44
|
+
when /\.gif$/
|
45
|
+
'image/gif'
|
46
|
+
when /(\.jpg|\.jpeg)$/
|
47
|
+
'image/jpeg'
|
48
|
+
when /\.png$/
|
49
|
+
'image/png'
|
50
|
+
when /\.swf$/
|
51
|
+
'application/x-shockwave-flash'
|
52
|
+
else
|
53
|
+
'application/binary'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#
|
2
|
+
# These are theme helper tags
|
3
|
+
#
|
4
|
+
module ActionView
|
5
|
+
module Helpers
|
6
|
+
module AssetTagHelper
|
7
|
+
|
8
|
+
# TODO: Convert these to user the named route helpers (?)
|
9
|
+
|
10
|
+
# returns the public path to a theme stylesheet
|
11
|
+
def theme_stylesheet_path( source=nil, theme=nil )
|
12
|
+
theme = theme || controller.current_theme
|
13
|
+
compute_public_path(source || "theme", "themes/#{theme}/stylesheets", 'css')
|
14
|
+
end
|
15
|
+
|
16
|
+
# returns the path to a theme image
|
17
|
+
def theme_image_path( source, theme=nil )
|
18
|
+
theme = theme || controller.current_theme
|
19
|
+
compute_public_path(source, "themes/#{theme}/images", 'png')
|
20
|
+
end
|
21
|
+
|
22
|
+
# returns the path to a theme javascript
|
23
|
+
def theme_javascript_path( source, theme=nil )
|
24
|
+
theme = theme || controller.current_theme
|
25
|
+
compute_public_path(source, "themes/#{theme}/javascript", 'js')
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
# This tag it will automatially include the 'theme' css, plus any other
|
30
|
+
# stylesheets you include in the params...
|
31
|
+
# This doesn't support overriding the Theme -- it will use the current theme
|
32
|
+
def theme_stylesheet_link_tag(*sources)
|
33
|
+
sources << controller.current_theme.to_s
|
34
|
+
sources.uniq!
|
35
|
+
options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { }
|
36
|
+
sources.collect { |source|
|
37
|
+
source = theme_stylesheet_path(source)
|
38
|
+
tag("link", { "rel" => "Stylesheet", "type" => "text/css", "media" => "screen", "href" => source }.merge(options))
|
39
|
+
}.join("\n")
|
40
|
+
end
|
41
|
+
|
42
|
+
# This tag will return a theme-specific IMG
|
43
|
+
def theme_image_tag(source, options = {})
|
44
|
+
options.symbolize_keys
|
45
|
+
|
46
|
+
options[:src] = theme_image_path(source)
|
47
|
+
options[:alt] ||= File.basename(options[:src], '.*').split('.').first.capitalize
|
48
|
+
|
49
|
+
if options[:size]
|
50
|
+
options[:width], options[:height] = options[:size].split("x")
|
51
|
+
options.delete :size
|
52
|
+
end
|
53
|
+
|
54
|
+
tag("img", options)
|
55
|
+
end
|
56
|
+
|
57
|
+
# This tag can be used to return theme-specific javscripts
|
58
|
+
def theme_javascript_include_tag(*sources)
|
59
|
+
options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { }
|
60
|
+
sources = ['prototype', 'effects', 'controls', 'dragdrop'] if sources.first == :defaults
|
61
|
+
sources.collect { |source|
|
62
|
+
source = theme_javascript_path(source)
|
63
|
+
content_tag("script", "", { "type" => "text/javascript", "src" => source }.merge(options))
|
64
|
+
}.join("\n")
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/theme_generator.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
class ThemeGenerator < Rails::Generator::NamedBase
|
2
|
+
def manifest
|
3
|
+
record do |m|
|
4
|
+
# Readme file
|
5
|
+
m.template 'README', "README_THEMES"
|
6
|
+
|
7
|
+
# Theme folder(s)
|
8
|
+
m.directory File.join( "themes", file_name )
|
9
|
+
m.template 'about.markdown', File.join( 'themes', file_name, 'about.markdown' )
|
10
|
+
m.template 'preview.png', File.join( 'themes', file_name, 'preview.png' )
|
11
|
+
|
12
|
+
m.directory File.join( "themes", file_name, "stylesheets" )
|
13
|
+
m.template "theme.css", File.join( "themes", file_name, "stylesheets", "#{file_name}.css" )
|
14
|
+
|
15
|
+
m.directory File.join( "themes", file_name, "layouts" )
|
16
|
+
m.template 'layout.rhtml', File.join( 'themes', file_name, 'layouts', 'default.rhtml' )
|
17
|
+
|
18
|
+
m.directory File.join( "themes", file_name, "views" )
|
19
|
+
m.directory File.join( "themes", file_name, "images" )
|
20
|
+
m.directory File.join( "themes", file_name, "javascript" )
|
21
|
+
|
22
|
+
# The ThemeEngine plugins
|
23
|
+
m.directory File.join( "vendor", "plugins", "theme_engine" )
|
24
|
+
m.template 'init.rb', File.join( 'vendor', 'plugins', 'theme_engine', 'init.rb' )
|
25
|
+
m.directory File.join( "vendor", "plugins", "theme_engine", "lib" )
|
26
|
+
m.template 'actioncontroller_ex.rb', File.join( 'vendor', 'plugins', 'theme_engine', 'lib', 'actioncontroller_ex.rb' )
|
27
|
+
m.template 'actionview_ex.rb', File.join( 'vendor', 'plugins', 'theme_engine', 'lib', 'actionview_ex.rb' )
|
28
|
+
m.template 'routeset_ex.rb', File.join( 'vendor', 'plugins', 'theme_engine', 'lib', 'routeset_ex.rb' )
|
29
|
+
m.template 'theme_helpers.rb', File.join( 'vendor', 'plugins', 'theme_engine', 'lib', 'theme_helpers.rb' )
|
30
|
+
|
31
|
+
# The ThemeSystem Component
|
32
|
+
m.directory File.join( "components", "theme_system" )
|
33
|
+
m.template 'theme.rb', File.join( 'components', 'theme_system', 'theme.rb' )
|
34
|
+
m.template 'theme_controller.rb', File.join( 'components', 'theme_system', 'theme_controller.rb' )
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: theme_generator
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.1.0
|
7
|
+
date: 2005-10-27 00:00:00 -05:00
|
8
|
+
summary: "[Rails] Theme generator adds support for themes into Rails applications"
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: darthapo@gmail.com
|
12
|
+
homepage: http://www.mattmccray.com
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
signing_key:
|
28
|
+
cert_chain:
|
29
|
+
authors:
|
30
|
+
- M@ McCray
|
31
|
+
files:
|
32
|
+
- templates/README
|
33
|
+
- templates/actionview_ex.rb
|
34
|
+
- templates/preview.png
|
35
|
+
- templates/theme.rb
|
36
|
+
- templates/about.markdown
|
37
|
+
- templates/init.rb
|
38
|
+
- templates/routeset_ex.rb
|
39
|
+
- templates/theme_controller.rb
|
40
|
+
- templates/actioncontroller_ex.rb
|
41
|
+
- templates/layout.rhtml
|
42
|
+
- templates/theme.css
|
43
|
+
- templates/theme_helpers.rb
|
44
|
+
- USAGE
|
45
|
+
- theme_generator.rb
|
46
|
+
test_files: []
|
47
|
+
rdoc_options: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
requirements: []
|
52
|
+
dependencies:
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: rails
|
55
|
+
version_requirement:
|
56
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
57
|
+
requirements:
|
58
|
+
-
|
59
|
+
- ">"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.0.0
|
62
|
+
version:
|