extjs-theme 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +14 -14
- data/bin/xtheme +15 -5
- data/lib/extjs-theme.rb +99 -5
- data/lib/extjs-theme/cli.rb +78 -0
- data/lib/extjs-theme/template/defines.sass +7 -7
- data/test/config/xtheme.yml +2 -2
- data/test/extjs-xtheme_test.rb +1 -1
- data/test/public/stylesheets/themes/foo/all.sass +2 -2
- data/test/public/stylesheets/themes/foo/defines.sass +7 -7
- data/test/public/stylesheets/themes/foo/structure/structure.sass +1 -1
- data/test/public/stylesheets/themes/foo/visual/visual.sass +1 -1
- metadata +5 -13
- data/lib/extjs-theme/command.rb +0 -87
- data/lib/extjs-theme/commands/base.rb +0 -74
- data/lib/extjs-theme/commands/config.rb +0 -57
- data/lib/extjs-theme/commands/effects.rb +0 -15
- data/lib/extjs-theme/commands/help.rb +0 -83
- data/lib/extjs-theme/commands/theme.rb +0 -47
- data/lib/extjs-theme/dependencies.rb +0 -18
- data/lib/extjs-theme/effects.rb +0 -57
- data/lib/extjs-theme/generator.rb +0 -98
data/README.rdoc
CHANGED
@@ -22,9 +22,9 @@ to you Gemfile and execute
|
|
22
22
|
|
23
23
|
In the root of your Rails app, first execute the following in your console:
|
24
24
|
|
25
|
-
$ bundle exec xtheme init
|
25
|
+
$ bundle exec xtheme init <path/to/ext> <path/to/stylesheets/sass-dir>
|
26
26
|
|
27
|
-
This creates a YAML config file named config/xtheme.yml in the application root.
|
27
|
+
This creates a YAML config file named config/xtheme.yml in the application root. </path/to/ext> defaults to <code>public/javascripts/ext-3.2</code> and </path/to/stylesheets/sass-dir> defaults to <code>public/stylesheets/themes</code>.
|
28
28
|
|
29
29
|
---
|
30
30
|
theme_dir: app/stylesheets/themes
|
@@ -44,43 +44,43 @@ To generate a new Sass theme:
|
|
44
44
|
|
45
45
|
$ bundle exec xtheme create my-theme
|
46
46
|
|
47
|
-
In Rails, this will have created a new directory <code>public/stylesheets/
|
47
|
+
In Rails, this will have created a new directory <code>public/stylesheets/themes/my-theme</code>
|
48
48
|
|
49
49
|
The generator creates a main include file called <code>my-theme/all.sass</code> which contains <code>@include</code> directives for each individual Ext stylesheet. You *no longer need* to include the ext-all.css file from the Ext library -- <code>my-theme/all.sass</code> contains all it needs. In a Rails view, you would include this file in the standard Haml/Sass[http://sass-lang.com/] manner.
|
50
50
|
|
51
|
-
=stylesheet_link_tag "my-theme/
|
51
|
+
=stylesheet_link_tag "my-theme/all"
|
52
52
|
|
53
53
|
or in an <code>erb</code> template:
|
54
54
|
|
55
|
-
<%= stylesheet_link_tag "my-theme/
|
55
|
+
<%= stylesheet_link_tag "my-theme/all"
|
56
56
|
|
57
57
|
The generator also creates a copy of all the Ext theme images in <code>my-theme/images</code>
|
58
58
|
|
59
59
|
Another important sass file created is <code>my-theme/defines.sass</code>. This file contains Sass variable declarations added to each Ext sass file.
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
$img_path: '../themes/my-theme/images'
|
62
|
+
$font: tahoma,arial,verdana,sans-serif
|
63
|
+
$hue: -90.0
|
64
64
|
|
65
|
-
|
65
|
+
For more on Haml and Sass, consult the HAML documentation[http://haml-lang.com/] to learn about including Sass[http://sass-lang.com/] stylesheets.
|
66
66
|
|
67
67
|
== Effects
|
68
68
|
|
69
69
|
The Gem includes commands for theme colorization, including image-processing through RMagick.
|
70
70
|
|
71
|
-
Currently, the only effect available is <code>
|
71
|
+
Currently, the only effect available is <code>modulate</code>, for modifying the _hue_, _saturation_ and _lightness_ of a theme according to RMagick[http://www.imagemagick.org/RMagick/doc/image2.html#modulate]:
|
72
72
|
|
73
|
-
$ bundle exec xtheme
|
73
|
+
$ bundle exec xtheme modulate <theme-name> <hue> <saturation> <lightness>
|
74
74
|
|
75
|
-
The parameters _hue_, _saturation_ and _lightness_ are defined as {"Float numbers, for example, 0.25 means "25%".
|
75
|
+
The parameters _hue_, _saturation_ and _lightness_ are defined as {"Float numbers, for example, 0.25 means "25%". The median value of each argument is 1.0, that is, 100%"}[http://www.imagemagick.org/RMagick/doc/image2.html#modulate]
|
76
76
|
|
77
77
|
Based upon the default blue Ext theme, the following will generate a pink theme:
|
78
78
|
|
79
|
-
$ bundle exec xtheme
|
79
|
+
$ bundle exec xtheme modulate my-theme 0.5 1.0 1.0
|
80
80
|
|
81
81
|
A green theme:
|
82
82
|
|
83
|
-
$ bundle exec xtheme
|
83
|
+
$ bundle exec xtheme modulate my-theme 1.5 1.0 1.0
|
84
84
|
|
85
85
|
*Only hue works currently, saturation and lightness are under development*
|
86
86
|
|
data/bin/xtheme
CHANGED
@@ -5,10 +5,20 @@ require 'rubygems'
|
|
5
5
|
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
|
6
6
|
|
7
7
|
require 'extjs-theme'
|
8
|
-
require 'extjs-theme/
|
8
|
+
require 'extjs-theme/cli'
|
9
9
|
|
10
|
-
|
11
|
-
ARGV
|
12
|
-
|
10
|
+
begin
|
11
|
+
ExtJS::Theme::CLI.start(ARGV, {})
|
12
|
+
rescue ExtJS::Theme::Error => e
|
13
|
+
puts e.message
|
14
|
+
exit e.status_code
|
15
|
+
end
|
13
16
|
|
14
|
-
|
17
|
+
# GET RID OF THIS ONCE Thor is in place
|
18
|
+
#require 'extjs-theme/command'
|
19
|
+
|
20
|
+
#args = ARGV.dup
|
21
|
+
#ARGV.clear
|
22
|
+
#command = args.shift.strip rescue 'help'
|
23
|
+
|
24
|
+
#ExtJS::Theme::Command.run(command, args)
|
data/lib/extjs-theme.rb
CHANGED
@@ -2,12 +2,106 @@
|
|
2
2
|
# XTheme
|
3
3
|
# A module for generating and colorizing ExtJS themes.
|
4
4
|
#
|
5
|
+
require 'fileutils'
|
6
|
+
require 'yaml'
|
7
|
+
require 'thor'
|
8
|
+
require 'thor/group'
|
9
|
+
require 'sass'
|
10
|
+
require 'sass/css'
|
11
|
+
require 'RMagick'
|
12
|
+
|
5
13
|
module ExtJS
|
6
14
|
module Theme
|
7
|
-
|
8
|
-
|
9
|
-
|
15
|
+
ROOT = File.dirname(__FILE__)
|
16
|
+
|
17
|
+
DEFAULT_EXT_DIR = "public/javascripts/ext-3.2"
|
18
|
+
DEFAULT_THEME_DIR = "public/stylesheets/themes"
|
19
|
+
|
20
|
+
##
|
21
|
+
# Define Error classes
|
22
|
+
#
|
23
|
+
class Error < StandardError
|
24
|
+
def self.status_code(code = nil)
|
25
|
+
return @code unless code
|
26
|
+
@code = code
|
27
|
+
end
|
10
28
|
|
11
|
-
|
12
|
-
|
29
|
+
def status_code
|
30
|
+
self.class.status_code
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class ArgumentError < Error; status_code(1); end
|
35
|
+
class ConfigurationNotFound < Error; status_code(2); end
|
36
|
+
class ConfigurationError < Error; status_code(3); end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Class Methods
|
40
|
+
#
|
41
|
+
class << self
|
42
|
+
|
43
|
+
##
|
44
|
+
# Xtheme config accessor
|
45
|
+
#
|
46
|
+
def [](key)
|
47
|
+
(@config ||= configure)[key]
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Convert css file to sass
|
52
|
+
# @param {String} file The css filename to convert to sass
|
53
|
+
# @return {String}
|
54
|
+
#
|
55
|
+
def css2sass(file)
|
56
|
+
sass = Sass::CSS.new(File.read(file)).render
|
57
|
+
sass.gsub!(/background-image: url\(\.\.\/images\/default(.*)\)/, 'background-image: url (#{$img_path+"\1"})')
|
58
|
+
sass.gsub!(/(.*):\s?#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/, '\1: adjust_hue(#\2, $hue)')
|
59
|
+
"@import '../defines.sass'\n#{sass}"
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Iterate all theme images and yield Magick::ImageList
|
64
|
+
#
|
65
|
+
def each_image
|
66
|
+
path = File.join(self['ext_dir'], "resources", "images", "default")
|
67
|
+
|
68
|
+
Dir["#{path}/*"].each do |dir|
|
69
|
+
Dir[dir+'/*.gif'].each do |filename|
|
70
|
+
yield(Magick::ImageList.new(filename))
|
71
|
+
end
|
72
|
+
Dir[dir+'/*.png'].each do |filename|
|
73
|
+
yield(Magick::ImageList.new(filename))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
# Now transform any images left in the base /images/default directory (excluding s.gif)
|
77
|
+
Dir["#{path}/*.*"].reject {|f| f.match('s.gif')}.each do |filename|
|
78
|
+
yield(Magick::ImageList.new(filename))
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Write transformed RMagick::Image to theme directory
|
84
|
+
# @param {RMagick::Image} img
|
85
|
+
# @param {String} dest Theme directory
|
86
|
+
#
|
87
|
+
def write_image(img, dest)
|
88
|
+
# Get filename and directory.
|
89
|
+
# Need to know if we're writing to /images/<package>/filename.gif OR /images/filename.gif
|
90
|
+
m = /\/default\/(.*)\/(.*)\.(.*)$/.match(img.filename) || /\/default\/(.*)\.(.*)$/.match(img.filename)
|
91
|
+
outfile = (m.captures.length == 3) ? File.join(dest, "images", m[1], "#{m[2]}.#{m[3]}") : File.join(dest, "images", "#{m[1]}.#{m[2]}")
|
92
|
+
img.write(outfile)
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def configure
|
98
|
+
unless File.exists?("config/xtheme.yml")
|
99
|
+
raise ConfigurationNotFound.new('This command must be run from inside a valid application')
|
100
|
+
end
|
101
|
+
cfg = YAML.load_file("config/xtheme.yml")
|
102
|
+
cfg["ext_dir"] = File.expand_path(cfg["ext_dir"])
|
103
|
+
cfg
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
13
107
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module ExtJS
|
2
|
+
module Theme
|
3
|
+
class CLI < Thor
|
4
|
+
include Thor::Actions
|
5
|
+
|
6
|
+
ARGV = ::ARGV.dup
|
7
|
+
|
8
|
+
##
|
9
|
+
# Required by thor
|
10
|
+
# Defines the source root-directory when copying files.
|
11
|
+
#
|
12
|
+
def self.source_root
|
13
|
+
ExtJS::Theme["ext_dir"]
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "init <path/to/ext> <path/to/stylesheets/sass-dir>", "Initialize extjs-theme for the current application. Creates config/xtheme.yml"
|
17
|
+
def init (ext_dir = ExtJS::Theme::DEFAULT_EXT_DIR, theme_dir = ExtJS::Theme::DEFAULT_THEME_DIR)
|
18
|
+
empty_directory("config") unless File.exists?("config")
|
19
|
+
inside("config") do
|
20
|
+
create_file("xtheme.yml", {
|
21
|
+
"ext_dir" => ext_dir,
|
22
|
+
"theme_dir" => theme_dir
|
23
|
+
}.to_yaml)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "create <theme-name>", "Creates a new sass-theme"
|
28
|
+
def create(name)
|
29
|
+
self.class.source_root
|
30
|
+
|
31
|
+
ext_css_path = File.join(ExtJS::Theme["ext_dir"], "resources", "css")
|
32
|
+
theme_path = File.join(ExtJS::Theme["theme_dir"], name)
|
33
|
+
|
34
|
+
# Create theme directory in /stylesheets/sass
|
35
|
+
FileUtils.mkdir_p ["#{theme_path}/visual", "#{theme_path}/structure"]
|
36
|
+
|
37
|
+
inside theme_path do
|
38
|
+
# load the defines.sass template file
|
39
|
+
data = File.read(File.join(File.dirname(__FILE__), "template", "defines.sass"))
|
40
|
+
img_path = theme_path.split("/")
|
41
|
+
img_path.shift # get rid of /public bit
|
42
|
+
|
43
|
+
# replace img_path sass_var with the location of theme's image-path
|
44
|
+
data.gsub!(/\{\{img_path\}\}/, File.join("/", img_path.join('/'), "images"))
|
45
|
+
|
46
|
+
# write contents to defines.sass
|
47
|
+
sass_files = [];
|
48
|
+
create_file("defines.sass", data, :force => true)
|
49
|
+
["structure", "visual"].each do |subdir|
|
50
|
+
inside subdir do
|
51
|
+
Dir["#{self.class.source_root}/resources/css/#{subdir}/*.css"].each do |file|
|
52
|
+
m = /^.*\/(.*)\.css$/.match(file)
|
53
|
+
sass_file = "#{m.captures[0]}.sass"
|
54
|
+
sass_files << "@import '#{File.join(subdir, sass_file)}'"
|
55
|
+
create_file(sass_file, ExtJS::Theme.css2sass(file), {:force => true})
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
create_file("all.sass", sass_files.join("\n"), {:force => true})
|
60
|
+
empty_directory("images")
|
61
|
+
FileUtils.cp_r("#{self.class.source_root}/resources/images/default/.", "images")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "modulate <theme> <hue> <saturation> <lightness>", "Modulate a theme. Specify h, s, l as floats, eg: 1.5"
|
66
|
+
def modulate(theme, hue, saturation, lightness)
|
67
|
+
ExtJS::Theme.each_image {|img|
|
68
|
+
path = img.filename.split('/')
|
69
|
+
filename = path.pop
|
70
|
+
dir = path.pop
|
71
|
+
say_status("modulate", File.join(dir, filename))
|
72
|
+
ExtJS::Theme.write_image(img.modulate(lightness.to_f, saturation.to_f, hue.to_f), File.join(ExtJS::Theme["theme_dir"], theme))
|
73
|
+
}
|
74
|
+
gsub_file(File.join(ExtJS::Theme["theme_dir"], theme, "defines.sass"), /\$hue:\s?(.*)/, "$hue: #{(hue.to_f-1)*180}")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
$bg_color: #eee
|
2
|
+
$bg_color_ghost: #cbddf3
|
3
|
+
$border_color: #0f0
|
4
|
+
$color: #333
|
5
|
+
$img_path:{{img_path}}
|
6
|
+
$font: tahoma,arial,verdana,sans-serif
|
7
|
+
$hue: 0
|
data/test/config/xtheme.yml
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
|
2
|
+
ext_dir: public/javascripts/ext-3.x
|
3
|
+
theme_dir: public/stylesheets/themes
|
data/test/extjs-xtheme_test.rb
CHANGED
@@ -34,7 +34,7 @@ class ThemeTest < Test::Unit::TestCase
|
|
34
34
|
FileUtils.rm(an_image)
|
35
35
|
|
36
36
|
# run the effect, it should create a newly modulated version of image (it should be green but how to tell?).
|
37
|
-
`xtheme
|
37
|
+
`xtheme modulate foo 1.5 1.0 1.0`
|
38
38
|
|
39
39
|
assert File.exists?(an_image), "Failed to modulate images"
|
40
40
|
end
|
@@ -1,2 +1,2 @@
|
|
1
|
-
@import structure/structure.sass
|
2
|
-
@import visual/visual.sass
|
1
|
+
@import 'structure/structure.sass'
|
2
|
+
@import 'visual/visual.sass'
|
@@ -1,7 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
$bg_color: #eee
|
2
|
+
$bg_color_ghost: #cbddf3
|
3
|
+
$border_color: #0f0
|
4
|
+
$color: #333
|
5
|
+
$img_path:/stylesheets/themes/foo/images
|
6
|
+
$font: tahoma,arial,verdana,sans-serif
|
7
|
+
$hue: 90.0
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Christopher Scott
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-21 00:00:00 -04:00
|
18
18
|
default_executable: xtheme
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -69,15 +69,7 @@ files:
|
|
69
69
|
- Rakefile
|
70
70
|
- bin/xtheme
|
71
71
|
- lib/extjs-theme.rb
|
72
|
-
- lib/extjs-theme/
|
73
|
-
- lib/extjs-theme/commands/base.rb
|
74
|
-
- lib/extjs-theme/commands/config.rb
|
75
|
-
- lib/extjs-theme/commands/effects.rb
|
76
|
-
- lib/extjs-theme/commands/help.rb
|
77
|
-
- lib/extjs-theme/commands/theme.rb
|
78
|
-
- lib/extjs-theme/dependencies.rb
|
79
|
-
- lib/extjs-theme/effects.rb
|
80
|
-
- lib/extjs-theme/generator.rb
|
72
|
+
- lib/extjs-theme/cli.rb
|
81
73
|
- lib/extjs-theme/template/defines.sass
|
82
74
|
- test/config/xtheme.yml
|
83
75
|
- test/extjs-xtheme_test.rb
|
data/lib/extjs-theme/command.rb
DELETED
@@ -1,87 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'commands/base'
|
3
|
-
|
4
|
-
Dir["#{File.dirname(__FILE__)}/commands/*"].each { |c| require c }
|
5
|
-
|
6
|
-
module ExtJS::Theme
|
7
|
-
module Command
|
8
|
-
class InvalidCommand < RuntimeError;
|
9
|
-
end
|
10
|
-
class CommandFailed < RuntimeError;
|
11
|
-
end
|
12
|
-
class InvalidConfig < RuntimeError;
|
13
|
-
end
|
14
|
-
class ConfigNotFound < RuntimeError;
|
15
|
-
end
|
16
|
-
|
17
|
-
class << self
|
18
|
-
def run(command, args, retries=0)
|
19
|
-
begin
|
20
|
-
run_internal(command, args.dup)
|
21
|
-
rescue InvalidCommand
|
22
|
-
error "Unknown command. Run 'xtheme help' for usage information."
|
23
|
-
rescue CommandFailed => e
|
24
|
-
error e.message
|
25
|
-
rescue InvalidConfig => e
|
26
|
-
error e.message
|
27
|
-
rescue ConfigNotFound => e
|
28
|
-
error e.message
|
29
|
-
rescue Interrupt => e
|
30
|
-
error "\n[canceled]"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def run_internal(command, args, heroku=nil)
|
35
|
-
config = load_config
|
36
|
-
|
37
|
-
klass, method = parse(command)
|
38
|
-
|
39
|
-
unless method == "init"
|
40
|
-
unless config
|
41
|
-
raise ConfigNotFound.new("Could not locate config file config/xtheme.yml.\nAre you in your application root? Have you run xtheme init?")
|
42
|
-
end
|
43
|
-
unless config && File.exists?(config[:ext_dir])
|
44
|
-
raise InvalidConfig.new("Could not locate ext_dir #{config[:ext_dir]}.\nAre you in your application root?")
|
45
|
-
end
|
46
|
-
unless config && File.exists?(config[:theme_dir])
|
47
|
-
raise InvalidConfig.new("Could not locate theme_dir #{config[:theme_dir]}.\nAre you in your application root?")
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
runner = klass.new(args, config)
|
52
|
-
raise InvalidCommand unless runner.respond_to?(method)
|
53
|
-
runner.send(method)
|
54
|
-
end
|
55
|
-
|
56
|
-
def error(msg)
|
57
|
-
STDERR.puts(msg)
|
58
|
-
exit 1
|
59
|
-
end
|
60
|
-
|
61
|
-
def parse(command)
|
62
|
-
parts = command.split(':')
|
63
|
-
case parts.size
|
64
|
-
when 1
|
65
|
-
begin
|
66
|
-
return eval("ExtJS::Theme::Command::#{command.capitalize}"), :index
|
67
|
-
rescue NameError, NoMethodError
|
68
|
-
return ExtJS::Theme::Command::Theme, command
|
69
|
-
end
|
70
|
-
when 2
|
71
|
-
begin
|
72
|
-
return ExtJS::Theme::Command.const_get(parts[0].capitalize), parts[1]
|
73
|
-
rescue NameError
|
74
|
-
raise InvalidCommand
|
75
|
-
end
|
76
|
-
else
|
77
|
-
raise InvalidCommand
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def load_config
|
82
|
-
FileUtils.mv('.xthemeconfig', 'config/xtheme.yml') if File.exists?('.xthemeconfig')
|
83
|
-
File.exists?('config/xtheme.yml') ? YAML::load(File.open('config/xtheme.yml')) : nil
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
|
-
module ExtJS::Theme::Command
|
4
|
-
class Base
|
5
|
-
#include Heroku::Helpers
|
6
|
-
|
7
|
-
attr_accessor :args
|
8
|
-
attr_reader :config
|
9
|
-
|
10
|
-
def initialize(args, config)
|
11
|
-
@args = args
|
12
|
-
@config = config
|
13
|
-
end
|
14
|
-
|
15
|
-
def display(msg, newline=true)
|
16
|
-
if newline
|
17
|
-
puts(msg)
|
18
|
-
else
|
19
|
-
print(msg)
|
20
|
-
STDOUT.flush
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def error(msg)
|
25
|
-
ExtJS::Theme::Command.error(msg)
|
26
|
-
end
|
27
|
-
|
28
|
-
def ask
|
29
|
-
gets.strip
|
30
|
-
end
|
31
|
-
|
32
|
-
def shell(cmd)
|
33
|
-
FileUtils.cd(Dir.pwd) {|d| return `#{cmd}`}
|
34
|
-
end
|
35
|
-
|
36
|
-
def heroku
|
37
|
-
#@heroku ||= Heroku::Command.run_internal('auth:client', args)
|
38
|
-
end
|
39
|
-
|
40
|
-
def extract_app(force=true)
|
41
|
-
app = extract_option('--app')
|
42
|
-
unless app
|
43
|
-
app = extract_app_in_dir(Dir.pwd) ||
|
44
|
-
raise(CommandFailed, "No app specified.\nRun this command from app folder or set it adding --app <app name>") if force
|
45
|
-
@autodetected_app = true
|
46
|
-
end
|
47
|
-
app
|
48
|
-
end
|
49
|
-
|
50
|
-
def extract_app_in_dir(dir)
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
def extract_option(options, default=true)
|
55
|
-
values = options.is_a?(Array) ? options : [options]
|
56
|
-
return unless opt_index = args.select { |a| values.include? a }.first
|
57
|
-
opt_position = args.index(opt_index) + 1
|
58
|
-
if args.size > opt_position && opt_value = args[opt_position]
|
59
|
-
if opt_value.include?('--')
|
60
|
-
opt_value = nil
|
61
|
-
else
|
62
|
-
args.delete_at(opt_position)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
opt_value ||= default
|
66
|
-
args.delete(opt_index)
|
67
|
-
block_given? ? yield(opt_value) : opt_value
|
68
|
-
end
|
69
|
-
|
70
|
-
def escape(value)
|
71
|
-
heroku.escape(value)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
module ExtJS::Theme::Command
|
2
|
-
class Config < Base
|
3
|
-
def index
|
4
|
-
#long = args.delete('--long')
|
5
|
-
#vars = heroku.config_vars(app)
|
6
|
-
#display_vars(vars, :long => long)
|
7
|
-
display "index"
|
8
|
-
end
|
9
|
-
|
10
|
-
def add
|
11
|
-
unless args.size > 0 and args.all? { |a| a.include?('=') }
|
12
|
-
raise CommandFailed, "Usage: xtheme config:add <key>=<value> [<key2>=<value2> ...]"
|
13
|
-
end
|
14
|
-
|
15
|
-
#vars = args.inject({}) do |vars, arg|
|
16
|
-
# key, value = arg.split('=', 2)
|
17
|
-
# vars[key] = value
|
18
|
-
# vars
|
19
|
-
#end
|
20
|
-
|
21
|
-
display "Adding config vars:"
|
22
|
-
#display_vars(vars, :indent => 2)
|
23
|
-
|
24
|
-
#display "Restarting app...", false
|
25
|
-
#heroku.add_config_vars(app, vars)
|
26
|
-
#display "done."
|
27
|
-
end
|
28
|
-
|
29
|
-
def remove
|
30
|
-
display "Removing #{args.first} and restarting app..."
|
31
|
-
#heroku.remove_config_var(app, args.first)
|
32
|
-
display "done."
|
33
|
-
end
|
34
|
-
|
35
|
-
alias :rm :remove
|
36
|
-
|
37
|
-
def clear
|
38
|
-
display "Clearing all config vars and restarting app..."
|
39
|
-
#heroku.clear_config_vars(app)
|
40
|
-
display "done."
|
41
|
-
end
|
42
|
-
|
43
|
-
protected
|
44
|
-
def display_vars(vars, options={})
|
45
|
-
max_length = vars.map { |v| v[0].size }.max
|
46
|
-
vars.keys.sort.each do |key|
|
47
|
-
spaces = ' ' * (max_length - key.size)
|
48
|
-
display "#{' ' * (options[:indent] || 0)}#{key}#{spaces} => #{format(vars[key], options)}"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def format(value, options)
|
53
|
-
return value if options[:long] || value.size < 36
|
54
|
-
value[0, 16] + '...' + value[-16, 16]
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module ExtJS::Theme::Command
|
2
|
-
class Effects < Base
|
3
|
-
|
4
|
-
def modulate
|
5
|
-
unless @args.length == 4
|
6
|
-
display "Usage: xtheme effects:modulate <theme-name> <hue> <saturation> <lightness>"
|
7
|
-
display " Specify <hue>, <saturation> and <lightness> as Floats, for example,"
|
8
|
-
display " 0.25 means 25%. The default value of each argument is 1.0, that is, 100%"
|
9
|
-
return
|
10
|
-
end
|
11
|
-
display "Modulating theme images"
|
12
|
-
ExtJS::Theme::Effects.modulate(@config[:ext_dir], "#{@config[:theme_dir]}/#{@args[0]}", @args[1].to_f, @args[2].to_f, @args[3].to_f)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
module ExtJS::Theme::Command
|
2
|
-
class Help < Base
|
3
|
-
class HelpGroup < Array
|
4
|
-
attr_reader :title
|
5
|
-
|
6
|
-
def initialize(title)
|
7
|
-
@title = title
|
8
|
-
end
|
9
|
-
|
10
|
-
def command(name, description)
|
11
|
-
self << [name, description]
|
12
|
-
end
|
13
|
-
|
14
|
-
def space
|
15
|
-
self << ['', '']
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.groups
|
20
|
-
@groups ||= []
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.group(title, &block)
|
24
|
-
groups << begin
|
25
|
-
group = HelpGroup.new(title)
|
26
|
-
group.instance_eval(&block)
|
27
|
-
group
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.create_default_groups!
|
32
|
-
group('General Commands') do
|
33
|
-
command 'help', 'show this usage'
|
34
|
-
#command 'version', 'show the gem version'
|
35
|
-
space
|
36
|
-
#command 'list', 'list your themes'
|
37
|
-
command 'create [<name>]', 'create a new theme'
|
38
|
-
space
|
39
|
-
#command 'config', 'display the theme\'s config vars (environment)'
|
40
|
-
#command 'config:add key=val [...]', 'add one or more config vars'
|
41
|
-
#space
|
42
|
-
#command 'destroy [<name>]', 'destroy a theme permanently'
|
43
|
-
end
|
44
|
-
|
45
|
-
group('Effects') do
|
46
|
-
command 'effects:modulate [<theme> <hue> <saturation> <lightness>]', 'Apply hue, saturation, lightness to a themes\'s images. Specify as Floats, where 1.0 means 100%'
|
47
|
-
space
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def index
|
52
|
-
display usage
|
53
|
-
end
|
54
|
-
|
55
|
-
def version
|
56
|
-
#display ExtJS::Theme.version
|
57
|
-
end
|
58
|
-
|
59
|
-
def usage
|
60
|
-
longest_command_length = self.class.groups.map do |group|
|
61
|
-
group.map { |g| g.first.length }
|
62
|
-
end.flatten.max
|
63
|
-
|
64
|
-
self.class.groups.inject(StringIO.new) do |output, group|
|
65
|
-
output.puts "=== %s" % group.title
|
66
|
-
output.puts ''
|
67
|
-
|
68
|
-
group.each do |command, description|
|
69
|
-
if command.empty?
|
70
|
-
output.puts ''
|
71
|
-
else
|
72
|
-
output.puts "%-*s # %s" % [longest_command_length, command, description]
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
output.puts ''
|
77
|
-
output
|
78
|
-
end.string
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
ExtJS::Theme::Command::Help.create_default_groups!
|
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
|
3
|
-
module ExtJS::Theme::Command
|
4
|
-
class Theme < Base
|
5
|
-
|
6
|
-
def init
|
7
|
-
|
8
|
-
ext_path = args[0] || 'public/javascripts/ext-3.2.0'
|
9
|
-
theme_path = args[1] || 'app/stylesheets/themes'
|
10
|
-
|
11
|
-
unless File.directory?(ext_path)
|
12
|
-
return display "Error: invalid ext js path: #{ext_path}"
|
13
|
-
end
|
14
|
-
|
15
|
-
unless File.directory?(theme_path)
|
16
|
-
FileUtils.mkdir_p(theme_path)
|
17
|
-
display "Create theme directory #{theme_path}"
|
18
|
-
end
|
19
|
-
|
20
|
-
display "Initializing xtheme configuration file config/xtheme.yml"
|
21
|
-
File.open("config/xtheme.yml", "w+") {|f|
|
22
|
-
f << {
|
23
|
-
:ext_dir => ext_path,
|
24
|
-
:theme_dir => theme_path
|
25
|
-
}.to_yaml
|
26
|
-
}
|
27
|
-
end
|
28
|
-
|
29
|
-
def list
|
30
|
-
display "Not implemented"
|
31
|
-
end
|
32
|
-
|
33
|
-
def create
|
34
|
-
name = args.shift.downcase.strip rescue nil
|
35
|
-
if !name
|
36
|
-
return display "Usage: xtheme create <name>"
|
37
|
-
end
|
38
|
-
ExtJS::Theme::Generator.create(name, @config[:ext_dir], @config[:theme_dir])
|
39
|
-
display "Created #{name}"
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
def destroy
|
44
|
-
display "Not implemented"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
gem 'haml-edge', '>= 2.3.0'
|
3
|
-
$stderr.puts "Loading haml-edge gem."
|
4
|
-
rescue LoadError
|
5
|
-
#pass
|
6
|
-
end
|
7
|
-
|
8
|
-
begin
|
9
|
-
gem 'rmagick'
|
10
|
-
$stderr.puts "Loading rmagick gem."
|
11
|
-
|
12
|
-
rescue LoadError
|
13
|
-
#pass
|
14
|
-
end
|
15
|
-
|
16
|
-
require 'sass'
|
17
|
-
require 'RMagick'
|
18
|
-
|
data/lib/extjs-theme/effects.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
module ExtJS::Theme
|
2
|
-
module Effects
|
3
|
-
|
4
|
-
##
|
5
|
-
# performs hsv transformation on Ext theme images and save to Sass theme dir.
|
6
|
-
# @param {String} name Theme name
|
7
|
-
# @param {String} ext_dir path to Ext directory relative to public/javascripts
|
8
|
-
# @param {Float} hue
|
9
|
-
# @param {Float} saturation
|
10
|
-
# @param {Float} lightness
|
11
|
-
#
|
12
|
-
def self.modulate(ext_dir, theme_dir, hue=1.0, saturation=1.0, lightness=1.0)
|
13
|
-
each_image("#{ext_dir}/resources/images/default") {|img|
|
14
|
-
write_image(img.modulate(lightness, saturation, hue), theme_dir)
|
15
|
-
}
|
16
|
-
# update hue in defines.sass
|
17
|
-
defines = File.read("#{theme_dir}/defines.sass")
|
18
|
-
File.open("#{theme_dir}/defines.sass", "w+") {|f| f << defines.gsub(/hue\s?=.*/, "hue = #{(hue-1)*180}") }
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
##
|
24
|
-
# Iterate all theme images
|
25
|
-
# @param {String} path
|
26
|
-
#
|
27
|
-
def self.each_image(path)
|
28
|
-
Dir["#{path}/*/"].each do |dir|
|
29
|
-
Dir[dir+'/*.gif'].each do |filename|
|
30
|
-
yield(Magick::ImageList.new(filename))
|
31
|
-
end
|
32
|
-
Dir[dir+'/*.png'].each do |filename|
|
33
|
-
yield(Magick::ImageList.new(filename))
|
34
|
-
end
|
35
|
-
end
|
36
|
-
# Now transform any images left in the base /images/default directory (excluding s.gif)
|
37
|
-
Dir["#{path}/*.*"].reject {|f| f.match('s.gif')}.each do |filename|
|
38
|
-
yield(Magick::ImageList.new(filename))
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
##
|
43
|
-
# Write transformed RMagick::Image to theme directory
|
44
|
-
# @param {RMagick::Image} img
|
45
|
-
# @param {String} dest Theme directory
|
46
|
-
#
|
47
|
-
def self.write_image(img, dest)
|
48
|
-
# Get filename and directory
|
49
|
-
m = /\/default\/(.*)\/(.*)\.(.*)$/.match(img.filename) || /\/default\/(.*)\.(.*)$/.match(img.filename)
|
50
|
-
#m = /\/(.*)\/(.*)\.(.*)$/.match(img.filename) || /\/(.*)\.(.*)$/.match(img.filename)
|
51
|
-
outfile = (m.captures.length == 3) ? "#{dest}/images/#{m[1]}#{m[2]}.#{m[3]}" : "#{dest}/images/#{m[1]}.#{m[2]}"
|
52
|
-
|
53
|
-
puts " - #{outfile}"
|
54
|
-
img.write(outfile)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,98 +0,0 @@
|
|
1
|
-
module ExtJS
|
2
|
-
module Theme
|
3
|
-
module Generator
|
4
|
-
##
|
5
|
-
# creates a new Sass theme
|
6
|
-
# @param {String} name
|
7
|
-
# @param {String} ext_dir path to Ext directory relative to public/javascripts
|
8
|
-
# @param {String} theme_dir Path to theme output dir (eg: stylesheets/sass)
|
9
|
-
#
|
10
|
-
def self.create(name, ext_dir, theme_dir)
|
11
|
-
ext_css_path = "#{ext_dir}/resources/css"
|
12
|
-
theme_path = "#{theme_dir}/#{name}"
|
13
|
-
|
14
|
-
# Create theme directory in /stylesheets/sass
|
15
|
-
FileUtils.mkdir_p ["#{theme_path}/visual", "#{theme_path}/structure"]
|
16
|
-
|
17
|
-
# Create the defines.sass file, set img_path variable.
|
18
|
-
FileUtils.copy("#{File.dirname(__FILE__)}/template/defines.sass", "#{theme_path}/defines.sass")
|
19
|
-
defines = File.read("#{theme_path}/defines.sass")
|
20
|
-
File.open("#{theme_path}/defines.sass", "w+") {|f| f << defines.gsub(/\{\{img_path\}\}/, "../themes/#{name}/images") }
|
21
|
-
puts " - created #{theme_path}/defines.sass"
|
22
|
-
|
23
|
-
sass_files = []
|
24
|
-
# Iterate each Ext css file and convert to Sass.
|
25
|
-
["structure", "visual"].each do |subdir|
|
26
|
-
puts " Converting #{subdir} styles to Sass"
|
27
|
-
Dir["#{ext_css_path}/#{subdir}/*.css"].each do |file|
|
28
|
-
m = /^.*\/(.*)\.css$/.match(file)
|
29
|
-
sass_file = "#{theme_path}/#{subdir}/#{m.captures[0]}.sass"
|
30
|
-
puts " - sass-convert #{m.captures[0]}.css -> #{sass_file}"
|
31
|
-
sass_files << "@import #{subdir}/#{m.captures[0]}.sass"
|
32
|
-
`sass-convert #{file} #{sass_file}`
|
33
|
-
write_sass_vars(sass_file)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# Create master sass file, which includes @imports for all other files in theme.
|
38
|
-
puts " - Writing all.sass"
|
39
|
-
f = File.new("#{theme_path}/all.sass", "w")
|
40
|
-
f.puts sass_files.join("\n")
|
41
|
-
|
42
|
-
# Copy Ext theme images to new Sass theme dir.
|
43
|
-
FileUtils.cp_r("#{ext_dir}/resources/images/default", "#{theme_path}/images")
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
##
|
50
|
-
# Iterate all theme images
|
51
|
-
# @param {String} path
|
52
|
-
#
|
53
|
-
def self.each_image(path)
|
54
|
-
Dir["#{path}/*/"].each do |dir|
|
55
|
-
Dir[dir+'/*.gif'].each do |filename|
|
56
|
-
yield(Magick::ImageList.new(filename))
|
57
|
-
end
|
58
|
-
Dir[dir+'/*.png'].each do |filename|
|
59
|
-
yield(Magick::ImageList.new(filename))
|
60
|
-
end
|
61
|
-
end
|
62
|
-
# Now transform any images left in the base /images/default directory (excluding s.gif)
|
63
|
-
Dir["#{path}/*.*"].reject {|f| f.match('s.gif')}.each do |filename|
|
64
|
-
yield(Magick::ImageList.new(filename))
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
##
|
69
|
-
# Searches .sass file for HEX colors and wraps in Sass adjust_hue function.
|
70
|
-
# Also substitutes urls with !img_path Sass var
|
71
|
-
# @param {String} filename of .sass file to write !vars to
|
72
|
-
#
|
73
|
-
def self.write_sass_vars(file)
|
74
|
-
sass = File.read(file)
|
75
|
-
sass.gsub!(/background-image: url\(\.\.\/images\/default/, 'background-image = url(!img_path')
|
76
|
-
sass.gsub!(/\b(.*):\s?#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/, '\1 = adjust_hue(#\2, !hue)')
|
77
|
-
|
78
|
-
# append @import "defines.sass" at start of each .sass file in order to use defined variables
|
79
|
-
File.open(file, "w") {|f| f << "@import ../defines.sass\n#{sass}" }
|
80
|
-
end
|
81
|
-
|
82
|
-
##
|
83
|
-
# Write transformed RMagick::Image to theme directory
|
84
|
-
# @param {RMagick::Image} img
|
85
|
-
# @param {String} dest Theme directory
|
86
|
-
#
|
87
|
-
def self.write_image(img, dest)
|
88
|
-
# Get filename and directory
|
89
|
-
m = /\/default\/(.*)\/(.*)\.(.*)$/.match(img.filename) || /\/default\/(.*)\.(.*)$/.match(img.filename)
|
90
|
-
#m = /\/(.*)\/(.*)\.(.*)$/.match(img.filename) || /\/(.*)\.(.*)$/.match(img.filename)
|
91
|
-
outfile = (m.captures.length == 3) ? "#{dest}/images/#{m[1]}#{m[2]}.#{m[3]}" : "#{dest}/images/#{m[1]}.#{m[2]}"
|
92
|
-
|
93
|
-
puts " - #{outfile}"
|
94
|
-
img.write(outfile)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|