extjs-theme 0.1.3 → 0.2.0
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.
- 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
|