compass-edge 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/Rakefile +34 -1
  2. data/VERSION.yml +3 -2
  3. data/features/command_line.feature +219 -0
  4. data/features/step_definitions/command_line_steps.rb +199 -0
  5. data/lib/compass/app_integration/rails/installer.rb +3 -1
  6. data/lib/compass/app_integration/stand_alone/installer.rb +26 -11
  7. data/lib/compass/commands.rb +1 -1
  8. data/lib/compass/commands/create_project.rb +8 -1
  9. data/lib/compass/commands/installer_command.rb +6 -2
  10. data/lib/compass/commands/project_stats.rb +160 -0
  11. data/lib/compass/commands/update_project.rb +49 -1
  12. data/lib/compass/commands/validate_project.rb +56 -2
  13. data/lib/compass/commands/watch_project.rb +3 -1
  14. data/lib/compass/commands/write_configuration.rb +60 -2
  15. data/lib/compass/compiler.rb +4 -3
  16. data/lib/compass/configuration/helpers.rb +9 -0
  17. data/lib/compass/errors.rb +4 -1
  18. data/lib/compass/exec.rb +1 -0
  19. data/lib/compass/frameworks/compass/stylesheets/compass/utilities/general/_reset.sass +2 -2
  20. data/lib/compass/installers.rb +1 -1
  21. data/lib/compass/installers/bare_installer.rb +62 -0
  22. data/lib/compass/installers/base.rb +7 -51
  23. data/lib/compass/installers/manifest_installer.rb +59 -0
  24. data/lib/compass/sass_extensions/monkey_patches.rb +2 -2
  25. data/lib/compass/sass_extensions/monkey_patches/traversal.rb +23 -0
  26. data/lib/compass/stats.rb +92 -0
  27. data/lib/compass/validator.rb +2 -3
  28. data/test/command_line_helper.rb +6 -2
  29. data/test/fixtures/stylesheets/compass/css/reset.css +1 -1
  30. data/test/io_helper.rb +18 -1
  31. data/test/rails_helper.rb +40 -0
  32. data/test/rails_integration_test.rb +2 -40
  33. data/test/test_helper.rb +1 -0
  34. metadata +12 -3
@@ -2,11 +2,13 @@ module Compass
2
2
  module Installers
3
3
  class Base
4
4
  end
5
+ class ManifestInstaller < Base
6
+ end
5
7
  end
6
8
 
7
9
  module AppIntegration
8
10
  module Rails
9
- class Installer < Compass::Installers::Base
11
+ class Installer < Compass::Installers::ManifestInstaller
10
12
 
11
13
  def default_configuration
12
14
  Compass::Configuration::Data.new.extend(ConfigurationDefaults)
@@ -2,11 +2,13 @@ module Compass
2
2
  module Installers
3
3
  class Base
4
4
  end
5
+ class ManifestInstaller < Base
6
+ end
5
7
  end
6
8
 
7
9
  module AppIntegration
8
10
  module StandAlone
9
- class Installer < Compass::Installers::Base
11
+ class Installer < Compass::Installers::ManifestInstaller
10
12
 
11
13
  def init
12
14
  directory targetize("")
@@ -45,16 +47,29 @@ module Compass
45
47
  if options[:create]
46
48
  puts <<-NEXTSTEPS
47
49
 
48
- Congratulations! Your compass project has been created.
49
- You must recompile your sass stylesheets when they change.
50
- This can be done in one of the following ways:
51
- 1. From within your project directory run:
52
- compass
53
- 2. From any directory run:
54
- compass -u path/to/project
55
- 3. To monitor your project for changes and automatically recompile:
56
- compass --watch [path/to/project]
57
- NEXTSTEPS
50
+ *********************************************************************
51
+ Congratulations! Your compass project has been created.
52
+
53
+ You may now add and edit sass stylesheets in the #{Compass.configuration.sass_dir} subdirectory of your project.
54
+
55
+ Sass files beginning with an underscore are called partials and won't be
56
+ compiled to CSS, but they can be imported into other sass stylesheets.
57
+
58
+ You can configure your project by editing the config.rb configuration file.
59
+
60
+ You must compile your sass stylesheets into CSS when they change.
61
+ This can be done in one of the following ways:
62
+ 1. To compile on demand:
63
+ compass compile [path/to/project]
64
+ 2. To monitor your project for changes and automatically recompile:
65
+ compass watch [path/to/project]
66
+
67
+ More Resources:
68
+ * Wiki: http://wiki.github.com/chriseppstein/compass
69
+ * Sass: http://sass-lang.com
70
+ * Community: http://groups.google.com/group/compass-users/
71
+
72
+ NEXTSTEPS
58
73
  end
59
74
  if manifest.has_stylesheet?
60
75
  puts "\nTo import your new stylesheets add the following lines of HTML (or equivalent) to your webpage:"
@@ -5,7 +5,7 @@ require 'compass/commands/registry'
5
5
 
6
6
  %w(base generate_grid_background help list_frameworks project_base
7
7
  update_project watch_project create_project installer_command
8
- print_version stamp_pattern validate_project
8
+ print_version project_stats stamp_pattern validate_project
9
9
  write_configuration).each do |lib|
10
10
  require "compass/commands/#{lib}"
11
11
  end
@@ -15,6 +15,10 @@ module Compass
15
15
 
16
16
  Options:
17
17
  }.split("\n").map{|l| l.gsub(/^ */,'')}.join("\n")
18
+
19
+ opts.on_tail("--bare", "Don't generate any Sass or CSS files.") do
20
+ self.options[:bare] = true
21
+ end
18
22
  else
19
23
  opts.banner = %Q{
20
24
  Usage: compass init project_type path/to/project [options]
@@ -68,6 +72,9 @@ module Compass
68
72
  parser = option_parser(arguments)
69
73
  parse_options!(parser, arguments)
70
74
  parse_arguments!(parser, arguments)
75
+ if parser.options[:framework] && parser.options[:bare]
76
+ raise Compass::Error, "A bare project cannot be created when a framework is specified."
77
+ end
71
78
  set_default_arguments(parser)
72
79
  parser.options
73
80
  end
@@ -92,7 +99,7 @@ module Compass
92
99
  if arguments.size == 1
93
100
  parser.options[:project_name] = arguments.shift
94
101
  elsif arguments.size == 0
95
- raise Compass::Error, "Please specify a path to the project."
102
+ # default to the current directory.
96
103
  else
97
104
  raise Compass::Error, "Too many arguments were specified."
98
105
  end
@@ -16,8 +16,12 @@ module Compass
16
16
  end
17
17
 
18
18
  def installer
19
- project_type = options[:project_type] || Compass.configuration.project_type
20
- installer_class = "Compass::AppIntegration::#{camelize(project_type)}::Installer"
19
+ installer_class = if options[:bare]
20
+ "Compass::Installers::BareInstaller"
21
+ else
22
+ project_type = options[:project_type] || Compass.configuration.project_type
23
+ "Compass::AppIntegration::#{camelize(project_type)}::Installer"
24
+ end
21
25
  @installer = eval("#{installer_class}.new *installer_args")
22
26
  end
23
27
 
@@ -0,0 +1,160 @@
1
+ require 'compass/commands/project_base'
2
+ require 'compass/commands/update_project'
3
+
4
+ module Compass
5
+ module Commands
6
+ module StatsOptionsParser
7
+ def set_options(opts)
8
+ opts.banner = %Q{
9
+ Usage: compass stats [path/to/project] [options]
10
+
11
+ Description:
12
+ Compile project at the path specified (or the current
13
+ directory if not specified) and then compute statistics
14
+ for the sass and css files in the project.
15
+
16
+ Options:
17
+ }.strip.split("\n").map{|l| l.gsub(/^ {0,10}/,'')}.join("\n")
18
+
19
+ super
20
+ end
21
+ end
22
+ class ProjectStats < UpdateProject
23
+
24
+ register :stats
25
+
26
+ def initialize(working_path, options)
27
+ super
28
+ assert_project_directory_exists!
29
+ end
30
+
31
+ def perform
32
+ super
33
+ require 'compass/stats'
34
+ compiler = new_compiler_instance
35
+ sass_files = sorted_sass_files(compiler)
36
+ rows = [[ :-, :-, :-, :-, :-, :-, :- ],
37
+ [ 'Filename', 'Rules', 'Properties', 'Mixins Defs', 'Mixins Used', 'CSS Rules', 'CSS Properties' ],
38
+ [ :-, :-, :-, :-, :-, :-, :- ]]
39
+ maximums = [ 8, 5, 10, 14, 11, 9, 14 ]
40
+ alignments = [ :left, :right, :right, :right, :right, :right, :right ]
41
+ delimiters = [ ['| ', ' |'], [' ', ' |'], [' ', ' |'], [' ', ' |'], [' ', ' |'], [' ', ' |'], [' ', ' |'] ]
42
+ totals = [ "Total (#{sass_files.size} files):", 0, 0, 0, 0, 0, 0 ]
43
+
44
+ sass_files.each do |sass_file|
45
+ css_file = compiler.corresponding_css_file(sass_file) unless sass_file[0..0] == '_'
46
+ row = filename_columns(sass_file)
47
+ row += sass_columns(sass_file)
48
+ row += css_columns(css_file)
49
+ row.each_with_index do |c, i|
50
+ maximums[i] = [maximums[i].to_i, c.size].max
51
+ totals[i] = totals[i] + c.to_i if i > 0
52
+ end
53
+ rows << row
54
+ end
55
+ rows << [:-] * 7
56
+ rows << totals.map{|t| t.to_s}
57
+ rows << [:-] * 7
58
+ rows.each do |row|
59
+ row.each_with_index do |col, i|
60
+ print pad(col, maximums[i], :align => alignments[i], :left => delimiters[i].first, :right => delimiters[i].last)
61
+ end
62
+ print "\n"
63
+ end
64
+ if @missing_css_parser
65
+ puts "\nInstall css_parser to enable stats on your css files:\n\n\tgem install css_parser"
66
+ end
67
+ end
68
+
69
+ def pad(c, max, options = {})
70
+ options[:align] ||= :left
71
+ if c == :-
72
+ filler = '-'
73
+ c = ''
74
+ else
75
+ filler = ' '
76
+ end
77
+ spaces = max - c.size
78
+ filled = filler * [spaces,0].max
79
+ "#{options[:left]}#{filled if options[:align] == :right}#{c}#{filled if options[:align] == :left}#{options[:right]}"
80
+ end
81
+
82
+ def sorted_sass_files(compiler)
83
+ sass_files = compiler.sass_files(:exclude_partials => false)
84
+ sass_files.map! do |s|
85
+ filename = Compass.deprojectize(s, File.join(Compass.configuration.project_path, Compass.configuration.sass_dir))
86
+ [s, File.dirname(filename), File.basename(filename)]
87
+ end
88
+ sass_files = sass_files.sort_by do |s,d,f|
89
+ File.join(d, f[0] == ?_ ? f[1..-1] : f)
90
+ end
91
+ sass_files.map!{|s,d,f| s}
92
+ end
93
+
94
+ def filename_columns(sass_file)
95
+ filename = Compass.deprojectize(sass_file, working_path)
96
+ [filename]
97
+ end
98
+
99
+ def sass_columns(sass_file)
100
+ sf = Compass::Stats::SassFile.new(sass_file)
101
+ sf.analyze!
102
+ %w(rule_count prop_count mixin_def_count mixin_count).map do |t|
103
+ sf.send(t).to_s
104
+ end
105
+ end
106
+
107
+ def css_columns(css_file)
108
+ if File.exists?(css_file)
109
+ cf = Compass::Stats::CssFile.new(css_file)
110
+ cf.analyze!
111
+ %w(selector_count prop_count).map do |t|
112
+ cf.send(t).to_s
113
+ end
114
+ else
115
+ return [ '--', '--' ]
116
+ end
117
+ rescue LoadError
118
+ @missing_css_parser = true
119
+ return [ 'DISABLED', 'DISABLED' ]
120
+ end
121
+
122
+ class << self
123
+
124
+ def option_parser(arguments)
125
+ parser = Compass::Exec::CommandOptionParser.new(arguments)
126
+ parser.extend(Compass::Exec::GlobalOptionsParser)
127
+ parser.extend(Compass::Exec::ProjectOptionsParser)
128
+ parser.extend(StatsOptionsParser)
129
+ end
130
+
131
+ def usage
132
+ option_parser([]).to_s
133
+ end
134
+
135
+ def description(command)
136
+ "Report statistics about your stylesheets"
137
+ end
138
+
139
+ def parse!(arguments)
140
+ parser = option_parser(arguments)
141
+ parser.parse!
142
+ parse_arguments!(parser, arguments)
143
+ parser.options
144
+ end
145
+
146
+ def parse_arguments!(parser, arguments)
147
+ if arguments.size == 1
148
+ parser.options[:project_name] = arguments.shift
149
+ elsif arguments.size == 0
150
+ # default to the current directory.
151
+ else
152
+ raise Compass::Error, "Too many arguments were specified."
153
+ end
154
+ end
155
+
156
+ end
157
+
158
+ end
159
+ end
160
+ end
@@ -3,8 +3,25 @@ require 'compass/compiler'
3
3
 
4
4
  module Compass
5
5
  module Commands
6
+ module CompileProjectOptionsParser
7
+ def set_options(opts)
8
+ opts.banner = %Q{
9
+ Usage: compass compile [path/to/project] [options]
10
+
11
+ Description:
12
+ compile project at the path specified or the current director if not specified.
13
+
14
+ Options:
15
+ }.split("\n").map{|l| l.gsub(/^ */,'')}.join("\n")
16
+
17
+ super
18
+ end
19
+ end
20
+
6
21
  class UpdateProject < ProjectBase
7
-
22
+
23
+ register :compile
24
+
8
25
  def initialize(working_path, options)
9
26
  super
10
27
  assert_project_directory_exists! unless dry_run?
@@ -33,6 +50,37 @@ module Compass
33
50
  :force => options[:force]).merge(additional_options))
34
51
  end
35
52
 
53
+ class << self
54
+ def option_parser(arguments)
55
+ parser = Compass::Exec::CommandOptionParser.new(arguments)
56
+ parser.extend(Compass::Exec::GlobalOptionsParser)
57
+ parser.extend(Compass::Exec::ProjectOptionsParser)
58
+ parser.extend(CompileProjectOptionsParser)
59
+ end
60
+
61
+ def usage
62
+ option_parser([]).to_s
63
+ end
64
+
65
+ def description(command)
66
+ "Compile Sass stylesheets to CSS"
67
+ end
68
+
69
+ def parse!(arguments)
70
+ parser = option_parser(arguments)
71
+ parser.parse!
72
+ parse_arguments!(parser, arguments)
73
+ parser.options
74
+ end
75
+
76
+ def parse_arguments!(parser, arguments)
77
+ if arguments.size == 1
78
+ parser.options[:project_name] = arguments.shift
79
+ elsif arguments.size > 1
80
+ raise Compass::Error, "Too many arguments were specified."
81
+ end
82
+ end
83
+ end
36
84
  end
37
85
  end
38
86
  end
@@ -3,8 +3,26 @@ require 'compass/commands/update_project'
3
3
 
4
4
  module Compass
5
5
  module Commands
6
+ module ValidationOptionsParser
7
+ def set_options(opts)
8
+ opts.banner = %Q{
9
+ Usage: compass validate [path/to/project] [options]
10
+
11
+ Description:
12
+ Compile project at the path specified or the current
13
+ directory if not specified and then validate the
14
+ generated CSS.
15
+
16
+ Options:
17
+ }.strip.split("\n").map{|l| l.gsub(/^ {0,10}/,'')}.join("\n")
18
+
19
+ super
20
+ end
21
+ end
6
22
  class ValidateProject < ProjectBase
7
-
23
+
24
+ register :validate
25
+
8
26
  def initialize(working_path, options)
9
27
  super
10
28
  assert_project_directory_exists!
@@ -16,6 +34,42 @@ module Compass
16
34
  Validator.new(project_css_subdirectory).validate()
17
35
  end
18
36
 
37
+ class << self
38
+
39
+ def option_parser(arguments)
40
+ parser = Compass::Exec::CommandOptionParser.new(arguments)
41
+ parser.extend(Compass::Exec::GlobalOptionsParser)
42
+ parser.extend(Compass::Exec::ProjectOptionsParser)
43
+ parser.extend(ValidationOptionsParser)
44
+ end
45
+
46
+ def usage
47
+ option_parser([]).to_s
48
+ end
49
+
50
+ def description(command)
51
+ "Validate your generated css."
52
+ end
53
+
54
+ def parse!(arguments)
55
+ parser = option_parser(arguments)
56
+ parser.parse!
57
+ parse_arguments!(parser, arguments)
58
+ parser.options
59
+ end
60
+
61
+ def parse_arguments!(parser, arguments)
62
+ if arguments.size == 1
63
+ parser.options[:project_name] = arguments.shift
64
+ elsif arguments.size == 0
65
+ # default to the current directory.
66
+ else
67
+ raise Compass::Error, "Too many arguments were specified."
68
+ end
69
+ end
70
+
71
+ end
72
+
19
73
  end
20
74
  end
21
- end
75
+ end
@@ -7,6 +7,8 @@ module Compass
7
7
  module Commands
8
8
  class WatchProject < UpdateProject
9
9
 
10
+ register :watch
11
+
10
12
  attr_accessor :last_update_time, :last_sass_files
11
13
 
12
14
  def perform
@@ -66,4 +68,4 @@ module Compass
66
68
 
67
69
  end
68
70
  end
69
- end
71
+ end
@@ -2,8 +2,29 @@ require 'compass/commands/project_base'
2
2
 
3
3
  module Compass
4
4
  module Commands
5
+ module ConfigurationOptionsParser
6
+ def set_options(opts)
7
+ opts.banner = %Q{
8
+ Usage: compass config [path/to/config_file.rb] [options]
9
+
10
+ Description:
11
+ Generate a configuration file for the options specified.
12
+ Compass will recognize configuration files in the
13
+ following locations relative to the project root:
14
+ * #{Compass::Configuration::Helpers::KNOWN_CONFIG_LOCATIONS.join("
15
+ * ")}
16
+ Any other location, and you'll need to specify it when working with the command line tool using the -c option.
17
+
18
+ Options:
19
+ }.strip.split("\n").map{|l| l.gsub(/^ {0,10}/,'')}.join("\n")
20
+
21
+ super
22
+ end
23
+ end
5
24
  class WriteConfiguration < ProjectBase
6
-
25
+
26
+ register :config
27
+
7
28
  include InstallerCommand
8
29
 
9
30
  def initialize(working_path, options)
@@ -16,6 +37,7 @@ module Compass
16
37
  end
17
38
 
18
39
  def perform
40
+ directory projectize(File.dirname(options[:configuration_file]))
19
41
  installer.write_configuration_files(options[:configuration_file])
20
42
  end
21
43
 
@@ -27,6 +49,42 @@ module Compass
27
49
  false
28
50
  end
29
51
 
52
+ class << self
53
+
54
+ def option_parser(arguments)
55
+ parser = Compass::Exec::CommandOptionParser.new(arguments)
56
+ parser.extend(Compass::Exec::GlobalOptionsParser)
57
+ parser.extend(Compass::Exec::ProjectOptionsParser)
58
+ parser.extend(ConfigurationOptionsParser)
59
+ end
60
+
61
+ def usage
62
+ option_parser([]).to_s
63
+ end
64
+
65
+ def description(command)
66
+ "Generate a configuration file for the provided command line options."
67
+ end
68
+
69
+ def parse!(arguments)
70
+ parser = option_parser(arguments)
71
+ parser.parse!
72
+ parse_arguments!(parser, arguments)
73
+ parser.options
74
+ end
75
+
76
+ def parse_arguments!(parser, arguments)
77
+ if arguments.size == 1
78
+ parser.options[:configuration_file] = arguments.shift
79
+ elsif arguments.size == 0
80
+ # default to the current directory.
81
+ else
82
+ raise Compass::Error, "Too many arguments were specified."
83
+ end
84
+ end
85
+
86
+ end
87
+
30
88
  end
31
89
  end
32
- end
90
+ end