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
@@ -13,8 +13,9 @@ module Compass
13
13
  self.options[:cache_location] ||= File.join(from, ".sass-cache")
14
14
  end
15
15
 
16
- def sass_files
17
- @sass_files || Dir.glob(separate("#{from}/**/[^_]*.sass"))
16
+ def sass_files(options = {})
17
+ exclude_partials = options.fetch(:exclude_partials, true)
18
+ @sass_files || Dir.glob(separate("#{from}/**/#{'[^_]' if exclude_partials}*.sass"))
18
19
  end
19
20
 
20
21
  def stylesheet_name(sass_file)
@@ -51,4 +52,4 @@ module Compass
51
52
  end
52
53
  end
53
54
  end
54
- end
55
+ end
@@ -66,6 +66,15 @@ module Compass
66
66
  File.join(project_path, *path.split('/'))
67
67
  end
68
68
 
69
+ def deprojectize(path, project_path = nil)
70
+ project_path ||= configuration.project_path
71
+ if path[0..(project_path.size - 1)] == project_path
72
+ path[(project_path.size + 1)..-1]
73
+ else
74
+ path
75
+ end
76
+ end
77
+
69
78
  # TODO: Deprecate the src/config.rb location.
70
79
  KNOWN_CONFIG_LOCATIONS = [".compass/config.rb", "config/compass.config", "config.rb", "src/config.rb"]
71
80
 
@@ -4,4 +4,7 @@ module Compass
4
4
 
5
5
  class FilesystemConflict < Error
6
6
  end
7
- end
7
+
8
+ class MissingDependency < Error
9
+ end
10
+ end
@@ -3,6 +3,7 @@ require 'optparse'
3
3
  require 'compass/logger'
4
4
  require 'compass/errors'
5
5
  require 'compass/actions'
6
+ require 'compass/installers'
6
7
  require 'compass/commands'
7
8
 
8
9
  module Compass::Exec
@@ -33,7 +33,7 @@
33
33
  q, blockquote
34
34
  +reset-quotation
35
35
 
36
- img a
36
+ a img
37
37
  +reset-image-anchor-border
38
38
 
39
39
 
@@ -57,7 +57,7 @@
57
57
  q, blockquote
58
58
  +reset-quotation
59
59
 
60
- img a
60
+ a img
61
61
  +reset-image-anchor-border
62
62
 
63
63
  //Mixins partials
@@ -1,3 +1,3 @@
1
- %w(manifest template_context base).each do |f|
1
+ %w(manifest template_context base manifest_installer bare_installer).each do |f|
2
2
  require "compass/installers/#{f}"
3
3
  end
@@ -0,0 +1,62 @@
1
+ module Compass
2
+ module Installers
3
+
4
+ class BareInstaller < Base
5
+ def default_configuration
6
+ Compass::Configuration::Data.new.extend(Compass::AppIntegration::StandAlone::ConfigurationDefaults)
7
+ end
8
+
9
+ def completed_configuration
10
+ nil
11
+ end
12
+
13
+ def init
14
+ directory targetize("")
15
+ directory targetize(Compass.configuration.sass_dir)
16
+ end
17
+
18
+ def prepare
19
+ end
20
+
21
+ def install
22
+ config_file ||= targetize('config.rb')
23
+ write_file config_file, config_contents
24
+ end
25
+
26
+ def config_contents
27
+ project_path, Compass.configuration.project_path = Compass.configuration.project_path, nil
28
+ Compass.configuration.serialize
29
+ ensure
30
+ Compass.configuration.project_path = project_path
31
+ end
32
+
33
+ def finalize(options = {})
34
+ puts <<-NEXTSTEPS
35
+
36
+ *********************************************************************
37
+ Congratulations! Your compass project has been created.
38
+
39
+ You may now add sass stylesheets to the #{Compass.configuration.sass_dir} subdirectory of your project.
40
+
41
+ Sass files beginning with an underscore are called partials and won't be
42
+ compiled to CSS, but they can be imported into other sass stylesheets.
43
+
44
+ You can configure your project by editing the config.rb configuration file.
45
+
46
+ You must compile your sass stylesheets into CSS when they change.
47
+ This can be done in one of the following ways:
48
+ 1. To compile on demand:
49
+ compass compile [path/to/project]
50
+ 2. To monitor your project for changes and automatically recompile:
51
+ compass watch [path/to/project]
52
+
53
+ More Resources:
54
+ * Wiki: http://wiki.github.com/chriseppstein/compass
55
+ * Sass: http://sass-lang.com
56
+ * Community: http://groups.google.com/group/compass-users/
57
+ NEXTSTEPS
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -7,21 +7,15 @@ module Compass
7
7
 
8
8
  attr_accessor :template_path, :target_path, :working_path
9
9
  attr_accessor :options
10
- attr_accessor :manifest
11
10
 
12
11
  def initialize(template_path, target_path, options = {})
13
12
  @template_path = template_path
14
13
  @target_path = target_path
15
14
  @working_path = Dir.getwd
16
15
  @options = options
17
- @manifest = Manifest.new(manifest_file, options) if template_path
18
16
  self.logger = options[:logger]
19
17
  end
20
18
 
21
- def manifest_file
22
- @manifest_file ||= File.join(template_path, "manifest.rb")
23
- end
24
-
25
19
  [:css_dir, :sass_dir, :images_dir, :javascripts_dir, :http_stylesheets_path].each do |dir|
26
20
  define_method dir do
27
21
  Compass.configuration.send(dir)
@@ -31,23 +25,6 @@ module Compass
31
25
  end
32
26
  end
33
27
 
34
- # Initializes the project to work with compass
35
- def init
36
- dirs = manifest.map do |entry|
37
- loc = send("install_location_for_#{entry.type}", entry.to, entry.options)
38
- File.dirname(loc)
39
- end
40
-
41
- if manifest.has_stylesheet?
42
- dirs << sass_dir
43
- dirs << css_dir
44
- end
45
-
46
- dirs.uniq.sort.each do |dir|
47
- directory targetize(dir)
48
- end
49
- end
50
-
51
28
  # Runs the installer.
52
29
  # Every installer must conform to the installation strategy of prepare, install, and then finalize.
53
30
  # A default implementation is provided for each step.
@@ -62,25 +39,14 @@ module Compass
62
39
  def prepare
63
40
  end
64
41
 
65
- def configure_option_with_default(opt)
66
- value = options[opt]
67
- value ||= begin
68
- default_method = "default_#{opt}".to_sym
69
- send(default_method) if respond_to?(default_method)
70
- end
71
- send("#{opt}=", value)
72
- end
73
-
74
- # The default install method. Calls install_<type> methods in the order specified by the manifest.
42
+ # The install method override this to install
75
43
  def install
76
- manifest.each do |entry|
77
- send("install_#{entry.type}", entry.from, entry.to, entry.options)
78
- end
44
+ raise "Not Yet Implemented"
79
45
  end
80
46
 
81
47
  # The default finalize method -- it is a no-op.
82
48
  # This could print out a message or something.
83
- def finalize
49
+ def finalize(options = {})
84
50
  end
85
51
 
86
52
  def compilation_required?
@@ -165,22 +131,12 @@ module Compass
165
131
  strip_trailing_separator File.join(template_path, separate(path))
166
132
  end
167
133
 
134
+ # Emits an HTML fragment that can be used to link to the compiled css files
168
135
  def stylesheet_links
169
- html = "<head>\n"
170
- manifest.each_stylesheet do |stylesheet|
171
- # Skip partials.
172
- next if File.basename(stylesheet.from)[0..0] == "_"
173
- media = if stylesheet.options[:media]
174
- %Q{ media="#{stylesheet.options[:media]}"}
175
- end
176
- ss_line = %Q{ <link href="#{http_stylesheets_path}/#{stylesheet.to.sub(/\.sass$/,'.css')}"#{media} rel="stylesheet" type="text/css" />}
177
- if stylesheet.options[:condition]
178
- ss_line = " <!--[if #{stylesheet.options[:condition]}]>\n #{ss_line}\n <![endif]-->"
179
- end
180
- html << ss_line + "\n"
181
- end
182
- html << "</head>"
136
+ ""
183
137
  end
184
138
  end
185
139
  end
186
140
  end
141
+ require 'compass/installers/bare_installer'
142
+ require 'compass/installers/manifest_installer'
@@ -0,0 +1,59 @@
1
+ module Compass
2
+ module Installers
3
+
4
+ class ManifestInstaller < Base
5
+
6
+ attr_accessor :manifest
7
+
8
+ def initialize(template_path, target_path, options = {})
9
+ super
10
+ @manifest = Manifest.new(manifest_file, options) if template_path
11
+ end
12
+
13
+ def manifest_file
14
+ @manifest_file ||= File.join(template_path, "manifest.rb")
15
+ end
16
+
17
+ # Initializes the project to work with compass
18
+ def init
19
+ dirs = manifest.map do |entry|
20
+ loc = send("install_location_for_#{entry.type}", entry.to, entry.options)
21
+ File.dirname(loc)
22
+ end
23
+
24
+ if manifest.has_stylesheet?
25
+ dirs << sass_dir
26
+ dirs << css_dir
27
+ end
28
+
29
+ dirs.uniq.sort.each do |dir|
30
+ directory targetize(dir)
31
+ end
32
+ end
33
+
34
+ # The default install method. Calls install_<type> methods in the order specified by the manifest.
35
+ def install
36
+ manifest.each do |entry|
37
+ send("install_#{entry.type}", entry.from, entry.to, entry.options)
38
+ end
39
+ end
40
+
41
+ def stylesheet_links
42
+ html = "<head>\n"
43
+ manifest.each_stylesheet do |stylesheet|
44
+ # Skip partials.
45
+ next if File.basename(stylesheet.from)[0..0] == "_"
46
+ media = if stylesheet.options[:media]
47
+ %Q{ media="#{stylesheet.options[:media]}"}
48
+ end
49
+ ss_line = %Q{ <link href="#{http_stylesheets_path}/#{stylesheet.to.sub(/\.sass$/,'.css')}"#{media} rel="stylesheet" type="text/css" />}
50
+ if stylesheet.options[:condition]
51
+ ss_line = " <!--[if #{stylesheet.options[:condition]}]>\n #{ss_line}\n <![endif]-->"
52
+ end
53
+ html << ss_line + "\n"
54
+ end
55
+ html << "</head>"
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,3 +1,3 @@
1
- %w(stylesheet_updating).each do |patch|
1
+ %w(stylesheet_updating traversal).each do |patch|
2
2
  require "compass/sass_extensions/monkey_patches/#{patch}"
3
- end
3
+ end
@@ -0,0 +1,23 @@
1
+ module Sass
2
+ module Tree
3
+ class Node
4
+ unless method_defined?(:visit_depth_first)
5
+ def visit_depth_first(visitor)
6
+ visitor.visit(self)
7
+ visitor.down(self) if children.any? and visitor.respond_to?(:down)
8
+ if is_a?(ImportNode) && visitor.import?(self)
9
+ root = Sass::Files.tree_for(import, @options)
10
+ imported_children = root.children
11
+ end
12
+
13
+ (imported_children || children).each do |child|
14
+ break if visitor.respond_to?(:stop?) && visitor.stop?
15
+ child.visit_depth_first(visitor)
16
+ end
17
+ visitor.up(self) if children.any?
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,92 @@
1
+ module Compass
2
+ module Stats
3
+ class StatsVisitor
4
+ attr_accessor :rule_count, :prop_count, :mixin_def_count, :mixin_count
5
+ def initialize
6
+ self.rule_count = 0
7
+ self.prop_count = 0
8
+ self.mixin_def_count = 0
9
+ self.mixin_count = 0
10
+ end
11
+ def visit(node)
12
+ self.prop_count += 1 if node.is_a?(Sass::Tree::PropNode) && !node.children.any?
13
+ if node.is_a?(Sass::Tree::RuleNode)
14
+ self.rule_count += node.rules.map{|r| r.split(/,/)}.flatten.compact.size
15
+ end
16
+ self.mixin_def_count += 1 if node.is_a?(Sass::Tree::MixinDefNode)
17
+ self.mixin_count += 1 if node.is_a?(Sass::Tree::MixinNode)
18
+ end
19
+ def up(node)
20
+ end
21
+ def down(node)
22
+ end
23
+ def import?(node)
24
+ return false
25
+ full_filename = node.send(:import)
26
+ full_filename != Compass.deprojectize(full_filename)
27
+ end
28
+ end
29
+ class CssFile
30
+ attr_accessor :path, :css
31
+ attr_accessor :selector_count, :prop_count
32
+ def initialize(path)
33
+ require 'css_parser'
34
+ self.path = path
35
+ self.css = CssParser::Parser.new
36
+ self.css.add_block!(contents)
37
+ self.selector_count = 0
38
+ self.prop_count = 0
39
+ end
40
+ def contents
41
+ @contents ||= File.read(path)
42
+ end
43
+ def lines
44
+ contents.inject(0){|m,c| m + 1 }
45
+ end
46
+ def analyze!
47
+ css.each_selector do |selector, declarations, specificity|
48
+ sels = selector.split(/,/).size
49
+ props = declarations.split(/;/).size
50
+ self.selector_count += sels
51
+ self.prop_count += props
52
+ end
53
+ end
54
+ end
55
+ class SassFile
56
+ attr_accessor :path
57
+ attr_reader :visitor
58
+ def initialize(path)
59
+ self.path = path
60
+ end
61
+ def contents
62
+ @contents ||= File.read(path)
63
+ end
64
+ def tree
65
+ @tree = Sass::Engine.new(contents, Compass.configuration.to_sass_engine_options).to_tree
66
+ end
67
+ def visit_tree!
68
+ @visitor = StatsVisitor.new
69
+ tree.visit_depth_first(@visitor)
70
+ @visitor
71
+ end
72
+ def analyze!
73
+ visit_tree!
74
+ end
75
+ def lines
76
+ contents.inject(0){|m,c| m + 1 }
77
+ end
78
+ def rule_count
79
+ visitor.rule_count
80
+ end
81
+ def prop_count
82
+ visitor.prop_count
83
+ end
84
+ def mixin_def_count
85
+ visitor.mixin_def_count
86
+ end
87
+ def mixin_count
88
+ visitor.mixin_count
89
+ end
90
+ end
91
+ end
92
+ end
@@ -2,9 +2,8 @@ begin
2
2
  require 'rubygems'
3
3
  require 'compass-validator'
4
4
  rescue LoadError
5
- puts %Q{The Compass CSS Validator could not be loaded. Please install it:
5
+ raise Compass::MissingDependency, %Q{The Compass CSS Validator could not be loaded. Please install it:
6
6
 
7
7
  sudo gem install chriseppstein-compass-validator --source http://gems.github.com/
8
8
  }
9
- exit(1)
10
- end
9
+ end
@@ -1,3 +1,5 @@
1
+ require 'timeout'
2
+
1
3
  module Compass::CommandLineHelper
2
4
  def compass(*arguments)
3
5
  options = arguments.last.is_a?(Hash) ? arguments.pop : {}
@@ -35,8 +37,10 @@ module Compass::CommandLineHelper
35
37
  end
36
38
  end
37
39
  else
38
- @last_result = capture_output do
39
- execute *arguments
40
+ @last_error = capture_warning do
41
+ @last_result = capture_output do
42
+ @last_exit_code = execute *arguments
43
+ end
40
44
  end
41
45
  end
42
46
  rescue Timeout::Error