guard-sass 0.7.1 → 1.0.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.md +19 -3
- data/lib/guard/sass/formatter.rb +13 -9
- data/lib/guard/sass/runner.rb +28 -6
- data/lib/guard/sass/version.rb +1 -1
- data/lib/guard/sass.rb +83 -8
- metadata +3 -2
data/README.md
CHANGED
@@ -15,7 +15,7 @@ Install the gem with:
|
|
15
15
|
|
16
16
|
Add it to your Gemfile:
|
17
17
|
|
18
|
-
gem 'guard-sass'
|
18
|
+
gem 'guard-sass', :require => false
|
19
19
|
|
20
20
|
And finally add a basic setup to your Guardfile with:
|
21
21
|
|
@@ -92,8 +92,24 @@ The following options can be passed to guard-sass:
|
|
92
92
|
:all_on_start => true # Compiles all sass files on start
|
93
93
|
# default: false
|
94
94
|
|
95
|
-
:
|
96
|
-
#
|
95
|
+
:compass => true # Enable Compass support with default Rails 3.1-compatible
|
96
|
+
# options. You can overwrite any of these options by passing
|
97
|
+
# a hash.
|
98
|
+
|
99
|
+
:compass => {
|
100
|
+
:images_dir => "app/assets/images",
|
101
|
+
:images_path => File.join(Dir.pwd, "app/assets/images"),
|
102
|
+
:http_images_path => "/assets",
|
103
|
+
:http_images_dir => "/assets",
|
104
|
+
:http_fonts_path => "/assets",
|
105
|
+
:http_fonts_dir => "/assets"
|
106
|
+
}
|
107
|
+
|
108
|
+
:smart_partials => true # Causes guard-sass to do dependency resolution and only
|
109
|
+
# recompile the files that need it when you update partials.
|
110
|
+
# If not on, then guard-sass will update all files when a
|
111
|
+
# partial is changed.
|
112
|
+
# default: false
|
97
113
|
|
98
114
|
:hide_success => true # Disable successful compilation messages.
|
99
115
|
# default: false
|
data/lib/guard/sass/formatter.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Guard
|
2
2
|
class Sass
|
3
|
-
|
3
|
+
|
4
4
|
# The formatter handles providing output to the user.
|
5
5
|
class Formatter
|
6
6
|
|
@@ -10,35 +10,39 @@ module Guard
|
|
10
10
|
def initialize(opts={})
|
11
11
|
@hide_success = opts.fetch(:hide_success, false)
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
# Show a success message and notification if successes are being shown.
|
15
15
|
#
|
16
16
|
# @param msg [String]
|
17
17
|
# @param opts [Hash]
|
18
18
|
def success(msg, opts={})
|
19
19
|
unless @hide_success
|
20
|
-
|
20
|
+
benchmark = nil
|
21
|
+
if time = opts.delete(:time)
|
22
|
+
benchmark = "[\e[33m%2.2fs\e[0m] " % time
|
23
|
+
end
|
24
|
+
::Guard::UI.info("\t\e[1;37mSass\e[0m %s%s" % [benchmark, msg], opts)
|
21
25
|
notify(opts[:notification], :image => :success)
|
22
26
|
end
|
23
27
|
end
|
24
|
-
|
28
|
+
|
25
29
|
# Show an error message and notification.
|
26
30
|
#
|
27
31
|
# @param msg [String]
|
28
32
|
# @param opts [Hash]
|
29
33
|
def error(msg, opts={})
|
30
|
-
::Guard::UI.error(msg, opts)
|
31
|
-
notify(opts[:notification], :image => :failed)
|
34
|
+
::Guard::UI.error("[Sass] #{msg}", opts)
|
35
|
+
notify(opts[:notification], :image => :failed)
|
32
36
|
end
|
33
|
-
|
37
|
+
|
34
38
|
# Show a system notification.
|
35
|
-
#
|
39
|
+
#
|
36
40
|
# @param msg [String]
|
37
41
|
# @param opts [Hash] See http://rubydoc.info/github/guard/guard/master/Guard/Notifier.notify
|
38
42
|
def notify(msg, opts={})
|
39
43
|
::Guard::Notifier.notify(msg, ({:title => "Guard::Sass"}).merge(opts))
|
40
44
|
end
|
41
|
-
|
45
|
+
|
42
46
|
end
|
43
47
|
end
|
44
48
|
end
|
data/lib/guard/sass/runner.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'sass'
|
2
|
+
require 'benchmark'
|
2
3
|
|
3
4
|
module Guard
|
4
5
|
class Sass
|
@@ -32,11 +33,33 @@ module Guard
|
|
32
33
|
changed_files = []
|
33
34
|
|
34
35
|
# Assume partials have been checked for previously, so no partials are included here
|
36
|
+
rinput = (options[:input] || "").reverse
|
37
|
+
routput = (options[:output] || "").reverse
|
38
|
+
|
39
|
+
input = options[:input] || ''
|
40
|
+
output = options[:output] || ''
|
41
|
+
|
42
|
+
max_length = files.map do |file|
|
43
|
+
file.sub(/^#{input}/, '').gsub(/^\//, '').length
|
44
|
+
end.max || 0
|
45
|
+
|
35
46
|
files.each do |file|
|
36
47
|
begin
|
37
|
-
css_file =
|
38
|
-
|
39
|
-
|
48
|
+
css_file = nil
|
49
|
+
time = Benchmark.realtime do
|
50
|
+
css_file = write_file(compile(file), get_output_dir(file), file)
|
51
|
+
end
|
52
|
+
|
53
|
+
short_file = file.sub(/^#{input}/, '').gsub(/^\//, '')
|
54
|
+
short_css_file = css_file.sub(/^#{output}/, '').gsub(/^\//, '')
|
55
|
+
|
56
|
+
message = if options[:noop]
|
57
|
+
"verified #{file} (#{time})"
|
58
|
+
else
|
59
|
+
"%s -> %s" % [short_file.ljust(max_length), short_css_file]
|
60
|
+
end
|
61
|
+
|
62
|
+
@formatter.success "#{message}", :notification => message, :time => time
|
40
63
|
changed_files << css_file
|
41
64
|
|
42
65
|
rescue ::Sass::SyntaxError => e
|
@@ -61,7 +84,6 @@ module Guard
|
|
61
84
|
:debug_info => options[:debug_info],
|
62
85
|
:line_numbers => options[:line_numbers]
|
63
86
|
}
|
64
|
-
|
65
87
|
::Sass::Engine.new(content, sass_options).render
|
66
88
|
end
|
67
89
|
|
@@ -91,7 +113,8 @@ module Guard
|
|
91
113
|
# @param file [String] Name of the file
|
92
114
|
# @return [String] Path of file written
|
93
115
|
def write_file(content, dir, file)
|
94
|
-
|
116
|
+
filename = File.basename(file).gsub(/(\.s?[ac]ss)+/, '.css')
|
117
|
+
path = File.join(dir, filename)
|
95
118
|
|
96
119
|
unless options[:noop]
|
97
120
|
FileUtils.mkdir_p(dir)
|
@@ -100,7 +123,6 @@ module Guard
|
|
100
123
|
|
101
124
|
path
|
102
125
|
end
|
103
|
-
|
104
126
|
end
|
105
127
|
end
|
106
128
|
end
|
data/lib/guard/sass/version.rb
CHANGED
data/lib/guard/sass.rb
CHANGED
@@ -46,16 +46,41 @@ module Guard
|
|
46
46
|
if options[:input]
|
47
47
|
load_paths << options[:input]
|
48
48
|
options[:output] = options[:input] unless options.has_key?(:output)
|
49
|
-
watchers << ::Guard::Watcher.new(%r{^#{ options
|
49
|
+
watchers << ::Guard::Watcher.new(%r{^#{ options[:input] }/(.+\.s[ac]ss)$})
|
50
50
|
end
|
51
|
-
|
52
51
|
options = DEFAULTS.merge(options)
|
52
|
+
|
53
|
+
if compass = options.delete(:compass)
|
54
|
+
require 'compass'
|
55
|
+
compass = {} unless compass.is_a?(Hash)
|
56
|
+
|
57
|
+
Compass.add_project_configuration
|
58
|
+
Compass.configuration.project_path ||= Dir.pwd
|
59
|
+
Compass.configuration.images_dir = compass[:images_dir] || "app/assets/images"
|
60
|
+
Compass.configuration.images_path = compass[:images_path] || File.join(Dir.pwd, "app/assets/images")
|
61
|
+
Compass.configuration.http_images_path = compass[:http_images_path] || "/assets"
|
62
|
+
Compass.configuration.http_images_dir = compass[:http_images_dir] || "/assets"
|
63
|
+
|
64
|
+
Compass.configuration.http_fonts_path = compass[:http_fonts_path] || "/assets"
|
65
|
+
Compass.configuration.http_fonts_dir = compass[:http_fonts_dir] || "/assets"
|
66
|
+
|
67
|
+
Compass.configuration.asset_cache_buster = Proc.new {|*| {:query => Time.now.to_i} }
|
68
|
+
options[:load_paths] ||= []
|
69
|
+
options[:load_paths] << Compass.configuration.sass_load_paths
|
70
|
+
end
|
71
|
+
|
53
72
|
options[:load_paths] += load_paths
|
73
|
+
options[:load_paths].flatten!
|
54
74
|
|
55
75
|
@runner = Runner.new(watchers, options)
|
56
76
|
super(watchers, options)
|
57
77
|
end
|
58
78
|
|
79
|
+
# @return [Array<String>] Paths of all sass/scss files
|
80
|
+
def files
|
81
|
+
Watcher.match_files self, Dir['**/*.s[ac]ss']
|
82
|
+
end
|
83
|
+
|
59
84
|
# If option set to run all on start, run all when started.
|
60
85
|
#
|
61
86
|
# @raise [:task_has_failed]
|
@@ -67,17 +92,66 @@ module Guard
|
|
67
92
|
#
|
68
93
|
# @raise [:task_has_failed]
|
69
94
|
def run_all
|
70
|
-
files
|
71
|
-
|
95
|
+
run_on_changes files.reject {|f| partial?(f) }
|
96
|
+
end
|
97
|
+
|
98
|
+
def resolve_partials_to_owners(paths, depth = 0)
|
99
|
+
# If we get more than 10 levels of includes deep, we're probably in an
|
100
|
+
# import loop.
|
101
|
+
return run_all if depth > 10
|
102
|
+
|
103
|
+
# Get all files that might have imports
|
104
|
+
root = options[:input]
|
105
|
+
root += '/' unless root.end_with?('/')
|
106
|
+
|
107
|
+
partials = paths.find_all {|f| partial?(f) }
|
108
|
+
paths -= partials
|
109
|
+
sub_paths = partials.map {|p|
|
110
|
+
# Remove root, need relative paths
|
111
|
+
p.sub(/^#{root}/, '')
|
112
|
+
}.map {|p|
|
113
|
+
# Make version without underscores
|
114
|
+
[p, p.gsub(/(\/|^)_/, '\\1')]
|
115
|
+
}.map {|ps|
|
116
|
+
# For each of those, make a version with extensions
|
117
|
+
ps.map {|p|
|
118
|
+
[p, p.gsub(/\.s[ac]ss$/, '')]
|
119
|
+
}
|
120
|
+
}.flatten
|
121
|
+
|
122
|
+
# Search through all eligible files and find those we need to recompile
|
123
|
+
joined_paths = sub_paths.map {|p| Regexp.escape(p) }.join('|')
|
124
|
+
matcher = /@import.*(:?#{joined_paths})/
|
125
|
+
importing = files.find_all {|file| open(file, 'r').read.match(matcher) }
|
126
|
+
paths += importing
|
127
|
+
|
128
|
+
# If any of the matched files were partials, then go ahead and walk up the
|
129
|
+
# import tree
|
130
|
+
if paths.any? {|f| partial?(f) }
|
131
|
+
paths = resolve_partials_to_owners(paths, depth + 1)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Return our resolved set of paths to recompile
|
135
|
+
paths
|
136
|
+
end
|
137
|
+
|
138
|
+
def run_with_partials(paths)
|
139
|
+
if options[:smart_partials]
|
140
|
+
paths = resolve_partials_to_owners(paths)
|
141
|
+
run_on_changes Watcher.match_files(self, paths) unless paths.nil?
|
142
|
+
else
|
143
|
+
run_all
|
144
|
+
end
|
72
145
|
end
|
73
146
|
|
74
|
-
#
|
75
|
-
# {#
|
147
|
+
# Builds the files given. If a 'partial' file is found (name begins with
|
148
|
+
# '_'), calls {#run_with_partials} so that files which include it are
|
149
|
+
# rebuilt.
|
76
150
|
#
|
77
151
|
# @param paths [Array<String>]
|
78
152
|
# @raise [:task_has_failed]
|
79
153
|
def run_on_changes(paths)
|
80
|
-
return
|
154
|
+
return run_with_partials(paths) if paths.any? {|f| partial?(f) }
|
81
155
|
|
82
156
|
changed_files, success = @runner.run(paths)
|
83
157
|
notify changed_files
|
@@ -102,8 +176,9 @@ module Guard
|
|
102
176
|
end
|
103
177
|
end
|
104
178
|
|
179
|
+
# @return Whether +path+ is a partial
|
105
180
|
def partial?(path)
|
106
|
-
File.basename(path)
|
181
|
+
File.basename(path).start_with? '_'
|
107
182
|
end
|
108
183
|
|
109
184
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: guard-sass
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-07-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: guard
|
@@ -114,3 +114,4 @@ signing_key:
|
|
114
114
|
specification_version: 3
|
115
115
|
summary: Guard gem for Sass
|
116
116
|
test_files: []
|
117
|
+
has_rdoc:
|