├── .document
├── .gitignore
├── LICENSE
├── README.rdoc
├── Rakefile
├── VERSION
├── bin
└── xtheme
├── extjs-theme.gemspec
├── lib
├── extjs-theme.rb
└── extjs-theme
│ ├── cli.rb
│ └── template
│ └── defines.sass
└── test
├── config
└── xtheme.yml
├── extjs-xtheme_test.rb
├── public
├── javascripts
│ └── ext-3.x
│ │ └── resources
│ │ ├── css
│ │ ├── structure
│ │ │ └── structure.css
│ │ └── visual
│ │ │ └── visual.css
│ │ └── images
│ │ └── default
│ │ └── rails.png
└── stylesheets
│ └── themes
│ └── foo
│ ├── all.sass
│ ├── defines.sass
│ ├── images
│ └── rails.png
│ ├── structure
│ └── structure.sass
│ └── visual
│ └── visual.sass
└── test_helper.rb
/.document:
--------------------------------------------------------------------------------
1 | README.rdoc
2 | lib/**/*.rb
3 | bin/*
4 | features/**/*.feature
5 | LICENSE
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.sw?
2 | .DS_Store
3 | coverage
4 | rdoc
5 | pkg
6 | .xthemeconfig
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.rdoc:
--------------------------------------------------------------------------------
1 | = extjs-theme
2 |
3 | Generates a Sass version of Ext theme. Includes methods for colorizing images.
4 |
5 | This Gem depends upon RMagick[http://gemcutter.org/gems/rmagick] and haml-edge[http://gemcutter.org/gems/haml-edge]
6 |
7 | == Installation
8 |
9 | The Gem is hosted at Gemcutter[http://gemcutter.com]. Install the gem with:
10 |
11 | gem install extjs-theme
12 |
13 | or add
14 |
15 | gem 'extjs-theme'
16 |
17 | to you Gemfile and execute
18 |
19 | $ bundle install
20 |
21 | == Usage
22 |
23 | In the root of your Rails app, first execute the following in your console:
24 |
25 | $ bundle exec xtheme init
26 |
27 | This creates a YAML config file named config/xtheme.yml in the application root. defaults to public/javascripts/ext-3.2
and defaults to public/stylesheets/themes
.
28 |
29 | ---
30 | theme_dir: app/stylesheets/themes
31 | ext_dir: public/javascripts/ext-3.2.0
32 |
33 | or generate a custom configuration file by execute the following in your console:
34 |
35 | $ bundle exec xtheme init
36 |
37 | Every subsequent xtheme command will act up those directories. If you download a new version of Ext, simply re-execute xtheme init
with the new path
38 |
39 | Example
40 |
41 | $ bundle exec xtheme init public/javascripts/ext-3.3.0
42 |
43 | To generate a new Sass theme:
44 |
45 | $ bundle exec xtheme create my-theme
46 |
47 | In Rails, this will have created a new directory public/stylesheets/themes/my-theme
48 |
49 | The generator creates a main include file called my-theme/all.sass
which contains @include
directives for each individual Ext stylesheet. You *no longer need* to include the ext-all.css file from the Ext library -- my-theme/all.sass
contains all it needs. In a Rails view, you would include this file in the standard Haml/Sass[http://sass-lang.com/] manner.
50 |
51 | =stylesheet_link_tag "my-theme/all"
52 |
53 | or in an erb
template:
54 |
55 | <%= stylesheet_link_tag "my-theme/all"
56 |
57 | The generator also creates a copy of all the Ext theme images in my-theme/images
58 |
59 | Another important sass file created is my-theme/defines.sass
. This file contains Sass variable declarations added to each Ext sass file.
60 |
61 | $img_path: '../themes/my-theme/images'
62 | $font: tahoma,arial,verdana,sans-serif
63 | $hue: -90.0
64 |
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 |
67 | == Effects
68 |
69 | The Gem includes commands for theme colorization, including image-processing through RMagick.
70 |
71 | Currently, the only effect available is modulate
, for modifying the _hue_, _saturation_ and _lightness_ of a theme according to RMagick[http://www.imagemagick.org/RMagick/doc/image2.html#modulate]:
72 |
73 | $ bundle exec xtheme modulate
74 |
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 |
77 | Based upon the default blue Ext theme, the following will generate a pink theme:
78 |
79 | $ bundle exec xtheme modulate my-theme 0.5 1.0 1.0
80 |
81 | A green theme:
82 |
83 | $ bundle exec xtheme modulate my-theme 1.5 1.0 1.0
84 |
85 | *Only hue works currently, saturation and lightness are under development*
86 |
87 | == Copyright
88 |
89 | Copyright (c) 2010 Christocracy. See LICENSE for details.
90 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'rake'
3 |
4 | begin
5 | require 'jeweler'
6 | Jeweler::Tasks.new do |gem|
7 | gem.name = "extjs-theme"
8 | gem.summary = %Q{Ext theme-generator and colorizer}
9 | gem.description = %Q{Generates Sass-based Ext themes. Includes methods for colorizing themes.}
10 | gem.email = "christocracy@gmail.com"
11 | gem.homepage = "http://github.com/extjs/extjs-theme"
12 | gem.authors = ["Christopher Scott"]
13 | gem.add_development_dependency "shoulda"
14 | gem.add_dependency "rmagick"
15 | gem.add_dependency "haml", ">= 3.0.0.beta"
16 | gem.files = %w(Rakefile) +
17 | Dir.glob("{bin,lib,test}/**/*")
18 |
19 |
20 | # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
21 | end
22 | Jeweler::GemcutterTasks.new
23 | rescue LoadError
24 | puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
25 | end
26 |
27 | require 'rake/testtask'
28 | Rake::TestTask.new(:test) do |test|
29 | test.libs << 'lib' << 'test'
30 | test.pattern = 'test/**/*_test.rb'
31 | test.verbose = true
32 | end
33 |
34 | begin
35 | require 'rcov/rcovtask'
36 | Rcov::RcovTask.new do |test|
37 | test.libs << 'test'
38 | test.pattern = 'test/**/*_test.rb'
39 | test.verbose = true
40 | end
41 | rescue LoadError
42 | task :rcov do
43 | abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
44 | end
45 | end
46 |
47 | task :test => :check_dependencies
48 |
49 | task :default => :test
50 |
51 | require 'rake/rdoctask'
52 | Rake::RDocTask.new do |rdoc|
53 | if File.exist?('VERSION')
54 | version = File.read('VERSION')
55 | else
56 | version = ""
57 | end
58 |
59 | rdoc.rdoc_dir = 'rdoc'
60 | rdoc.title = "extjs-xtheme #{version}"
61 | rdoc.rdoc_files.include('README*')
62 | rdoc.rdoc_files.include('lib/**/*.rb')
63 | end
64 |
--------------------------------------------------------------------------------
/VERSION:
--------------------------------------------------------------------------------
1 | 0.2.0
2 |
--------------------------------------------------------------------------------
/bin/xtheme:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | require 'rubygems'
4 |
5 | $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
6 |
7 | require 'extjs-theme'
8 | require 'extjs-theme/cli'
9 |
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
16 |
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)
--------------------------------------------------------------------------------
/extjs-theme.gemspec:
--------------------------------------------------------------------------------
1 | # Generated by jeweler
2 | # DO NOT EDIT THIS FILE DIRECTLY
3 | # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4 | # -*- encoding: utf-8 -*-
5 |
6 | Gem::Specification.new do |s|
7 | s.name = %q{extjs-theme}
8 | s.version = "0.2.0"
9 |
10 | s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11 | s.authors = ["Christopher Scott"]
12 | s.date = %q{2010-04-21}
13 | s.default_executable = %q{xtheme}
14 | s.description = %q{Generates Sass-based Ext themes. Includes methods for colorizing themes.}
15 | s.email = %q{christocracy@gmail.com}
16 | s.executables = ["xtheme"]
17 | s.extra_rdoc_files = [
18 | "LICENSE",
19 | "README.rdoc"
20 | ]
21 | s.files = [
22 | "Rakefile",
23 | "bin/xtheme",
24 | "lib/extjs-theme.rb",
25 | "lib/extjs-theme/cli.rb",
26 | "lib/extjs-theme/template/defines.sass",
27 | "test/config/xtheme.yml",
28 | "test/extjs-xtheme_test.rb",
29 | "test/public/javascripts/ext-3.x/resources/css/structure/structure.css",
30 | "test/public/javascripts/ext-3.x/resources/css/visual/visual.css",
31 | "test/public/javascripts/ext-3.x/resources/images/default/rails.png",
32 | "test/public/stylesheets/themes/foo/all.sass",
33 | "test/public/stylesheets/themes/foo/defines.sass",
34 | "test/public/stylesheets/themes/foo/images/rails.png",
35 | "test/public/stylesheets/themes/foo/structure/structure.sass",
36 | "test/public/stylesheets/themes/foo/visual/visual.sass",
37 | "test/test_helper.rb"
38 | ]
39 | s.homepage = %q{http://github.com/extjs/extjs-theme}
40 | s.rdoc_options = ["--charset=UTF-8"]
41 | s.require_paths = ["lib"]
42 | s.rubygems_version = %q{1.3.6}
43 | s.summary = %q{Ext theme-generator and colorizer}
44 | s.test_files = [
45 | "test/extjs-xtheme_test.rb",
46 | "test/test_helper.rb"
47 | ]
48 |
49 | if s.respond_to? :specification_version then
50 | current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
51 | s.specification_version = 3
52 |
53 | if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
54 | s.add_development_dependency(%q, [">= 0"])
55 | s.add_runtime_dependency(%q, [">= 0"])
56 | s.add_runtime_dependency(%q, [">= 3.0.0.beta"])
57 | else
58 | s.add_dependency(%q, [">= 0"])
59 | s.add_dependency(%q, [">= 0"])
60 | s.add_dependency(%q, [">= 3.0.0.beta"])
61 | end
62 | else
63 | s.add_dependency(%q, [">= 0"])
64 | s.add_dependency(%q, [">= 0"])
65 | s.add_dependency(%q, [">= 3.0.0.beta"])
66 | end
67 | end
68 |
69 |
--------------------------------------------------------------------------------
/lib/extjs-theme.rb:
--------------------------------------------------------------------------------
1 | ##
2 | # XTheme
3 | # A module for generating and colorizing ExtJS themes.
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 |
13 | module ExtJS
14 | module Theme
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
28 |
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//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
107 | end
108 |
--------------------------------------------------------------------------------
/lib/extjs-theme/cli.rb:
--------------------------------------------------------------------------------
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 ", "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 ", "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 ", "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
--------------------------------------------------------------------------------
/lib/extjs-theme/template/defines.sass:
--------------------------------------------------------------------------------
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
8 |
--------------------------------------------------------------------------------
/test/config/xtheme.yml:
--------------------------------------------------------------------------------
1 | ---
2 | ext_dir: public/javascripts/ext-3.x
3 | theme_dir: public/stylesheets/themes
4 |
--------------------------------------------------------------------------------
/test/extjs-xtheme_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 | FileUtils.cd("test")
3 |
4 | PUBLIC_PATH = "public"
5 | THEME_PATH = File.join(PUBLIC_PATH, "stylesheets", "themes")
6 |
7 | # Remove previously generated config and test theme before starting.
8 | FileUtils.rm("config/xtheme.yml") if File.exists?("config/xtheme.yml")
9 | FileUtils.rm_r(File.join(THEME_PATH, "foo")) if File.exists?(File.join(THEME_PATH, "foo"))
10 |
11 | class ThemeTest < Test::Unit::TestCase
12 | context "Within a valid Rails-like app" do
13 | setup {
14 | `xtheme init public/javascripts/ext-3.x #{THEME_PATH}`
15 | }
16 |
17 | should "config/xtheme.yml should exist" do
18 | assert File.exists?("config/xtheme.yml"), "Failed to create config/xtheme.yml"
19 | end
20 |
21 | should "generate a theme" do
22 | `xtheme create foo`
23 | assert (
24 | File.exists?(File.join(THEME_PATH, "foo", "all.sass")) &&
25 | File.exists?(File.join(THEME_PATH, "foo", "images", "rails.png")) &&
26 | File.exists?(File.join(THEME_PATH, "foo", "structure", "structure.sass")) &&
27 | File.exists?(File.join(THEME_PATH, "foo", "visual", "visual.sass"))
28 | ), "Failed to generate theme"
29 | end
30 |
31 | should "modulate a theme" do
32 | # first destroy existing default image.
33 | an_image = File.join(THEME_PATH, "foo", "images", "rails.png")
34 | FileUtils.rm(an_image)
35 |
36 | # run the effect, it should create a newly modulated version of image (it should be green but how to tell?).
37 | `xtheme modulate foo 1.5 1.0 1.0`
38 |
39 | assert File.exists?(an_image), "Failed to modulate images"
40 | end
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/test/public/javascripts/ext-3.x/resources/css/structure/structure.css:
--------------------------------------------------------------------------------
1 | body {
2 | width: 666px;
3 | }
--------------------------------------------------------------------------------
/test/public/javascripts/ext-3.x/resources/css/visual/visual.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: #000;
3 | }
4 | h1 {
5 | color: #F00;
6 | }
--------------------------------------------------------------------------------
/test/public/javascripts/ext-3.x/resources/images/default/rails.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/extjs/extjs-theme/f29f887ffef12ee395a755dbd44877bf8e4a301b/test/public/javascripts/ext-3.x/resources/images/default/rails.png
--------------------------------------------------------------------------------
/test/public/stylesheets/themes/foo/all.sass:
--------------------------------------------------------------------------------
1 | @import 'structure/structure.sass'
2 | @import 'visual/visual.sass'
--------------------------------------------------------------------------------
/test/public/stylesheets/themes/foo/defines.sass:
--------------------------------------------------------------------------------
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
8 |
--------------------------------------------------------------------------------
/test/public/stylesheets/themes/foo/images/rails.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/extjs/extjs-theme/f29f887ffef12ee395a755dbd44877bf8e4a301b/test/public/stylesheets/themes/foo/images/rails.png
--------------------------------------------------------------------------------
/test/public/stylesheets/themes/foo/structure/structure.sass:
--------------------------------------------------------------------------------
1 | @import '../defines.sass'
2 | body
3 | width: 666px
4 |
--------------------------------------------------------------------------------
/test/public/stylesheets/themes/foo/visual/visual.sass:
--------------------------------------------------------------------------------
1 | @import '../defines.sass'
2 | body
3 | background: black
4 |
5 | h1
6 | color: red
7 |
--------------------------------------------------------------------------------
/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'test/unit'
3 | require 'shoulda'
4 |
5 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6 | $LOAD_PATH.unshift(File.dirname(__FILE__))
7 | require 'extjs-theme'
8 |
9 | class Test::Unit::TestCase
10 | end
11 |
--------------------------------------------------------------------------------