sugamasao-saag 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/ChangeLog +3 -0
- data/README +40 -0
- data/TODO +5 -0
- data/bin/saag +17 -0
- data/lib/saag.rb +239 -0
- metadata +80 -0
data/ChangeLog
ADDED
data/README
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
= saag
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
SASS automatic monitor and generate CSS file.
|
6
|
+
SASS ファイルを監視し、変更があれば即座に CSS ファイルへ変換します。
|
7
|
+
手動で以下のコマンドを行うのと同等です。
|
8
|
+
% sass hoge.sass hoge.css
|
9
|
+
|
10
|
+
== Gem Installation
|
11
|
+
|
12
|
+
gem install sugamasao-saag --source http://gems.github.com
|
13
|
+
|
14
|
+
== Features/Problems
|
15
|
+
|
16
|
+
* Ruby 1.8.7 でのみ、動作確認を行っています
|
17
|
+
* 事前にSASS(HAML)のインストールが必要になります
|
18
|
+
|
19
|
+
== Synopsis
|
20
|
+
|
21
|
+
使用例:
|
22
|
+
% saag
|
23
|
+
引数を使用しない場合、コマンド実行者のカレントディレクトリを基点とし、*.sass ファイルを探し、対象ファイルとします。
|
24
|
+
また、出力される CSS ファイルは sass ファイルと同じ階層になります。
|
25
|
+
|
26
|
+
% saag -i /path/to/sass
|
27
|
+
-i オプションを使用することで、sass ファイルのあるディレクトリ(ファイル名でも可)を指定する事が可能です。
|
28
|
+
出力先は、上記と同様に、sass ファイルのあるディレクトリになります。
|
29
|
+
|
30
|
+
% saag -i /path/to/sass -o /path/to/css
|
31
|
+
-o オプションを使用することで、css の出力先ファイルを指定することができます。
|
32
|
+
出力先ファイルのディレクトリ構成は、-i オプションに依存します。
|
33
|
+
上記のオプションを指定、/path/to/sass/sub_dir/hoge.sass があった場合、出力先ディレクトリは
|
34
|
+
/path/to/css/sub_dir/hoge.css となります。
|
35
|
+
|
36
|
+
== Copyright
|
37
|
+
|
38
|
+
Author:: sugamasao <sugamasao@gmail.com>
|
39
|
+
License:: Ruby's
|
40
|
+
|
data/bin/saag
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# $Id$
|
3
|
+
|
4
|
+
# lib のパスを追加しておく
|
5
|
+
$LOAD_PATH.unshift(File.expand_path("#{File.dirname(__FILE__)}/../lib/"))
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'saag'
|
9
|
+
require 'sass'
|
10
|
+
rescue LoadError
|
11
|
+
require 'rubygems'
|
12
|
+
require 'saag'
|
13
|
+
require 'sass'
|
14
|
+
end
|
15
|
+
|
16
|
+
Saag.new(ARGV).run
|
17
|
+
|
data/lib/saag.rb
ADDED
@@ -0,0 +1,239 @@
|
|
1
|
+
# $Id$
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'logger'
|
5
|
+
require 'pp'
|
6
|
+
|
7
|
+
class Saag
|
8
|
+
Version = '0.1.0'
|
9
|
+
SASS_EXT = '.sass'
|
10
|
+
CSS_EXT = '.css'
|
11
|
+
|
12
|
+
def initialize(argv = [])
|
13
|
+
# parse option
|
14
|
+
@conf = {}
|
15
|
+
@exit = false
|
16
|
+
@logger = Logger.new(STDOUT)
|
17
|
+
@logger.level = Logger::INFO # default Log Level
|
18
|
+
|
19
|
+
begin
|
20
|
+
OptionParser.new do |opt|
|
21
|
+
opt.on('-i', '--input_path=VAL', 'input file path(directory or filename)') {|v| @conf[:in_path] = set_dir_path(v)}
|
22
|
+
opt.on('-o', '--output_path=VAL', 'generated css file output path') {|v| @conf[:out_path] = set_dir_path(v)}
|
23
|
+
opt.on('-r', '--render_opt=VAL', 'sass render option [nested or expanded or compact or compressed]' ){|v| @conf[:render_opt] = set_render_opt(v)}
|
24
|
+
opt.on('-v', '--version', 'show version' ){puts "#{self.class} #{Version}"; exit 1}
|
25
|
+
opt.on('-d', '--debug', 'log level to debug') {|v| @conf[:debug] = v}
|
26
|
+
end.parse!(argv)
|
27
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
|
28
|
+
@logger.error('invalid args...! looks for "-h" option')
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
|
32
|
+
@logger.info("sass file watching start... [app ver=#{Version}]")
|
33
|
+
@logger.level = Logger::DEBUG if @conf[:debug]
|
34
|
+
|
35
|
+
@logger.debug("args input_path => #{@conf[:in_path]}")
|
36
|
+
@logger.debug("args output_path => #{@conf[:out_path]}")
|
37
|
+
@logger.debug("args render_opt => #{@conf[:render_opt]}")
|
38
|
+
|
39
|
+
set_default_conf()
|
40
|
+
set_signal()
|
41
|
+
|
42
|
+
@logger.info("watching directory => #{@conf[:in_path]}")
|
43
|
+
@logger.info("output directory => #{@conf[:out_path]}")
|
44
|
+
end
|
45
|
+
|
46
|
+
def run
|
47
|
+
old_list = []
|
48
|
+
# メインループ
|
49
|
+
begin
|
50
|
+
loop do
|
51
|
+
old_list = main_loop(old_list)
|
52
|
+
break if @exit # SIGNAL を受けたりすると true
|
53
|
+
sleep 1
|
54
|
+
end
|
55
|
+
rescue SystemCallError => e
|
56
|
+
@logger.error("File I/O Error! [#{e.message}]")
|
57
|
+
rescue => e
|
58
|
+
@logger.error("FATLE Error! [#{e.message}]")
|
59
|
+
end
|
60
|
+
|
61
|
+
@logger.info("sass file watching exit...")
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def main_loop(old_list)
|
67
|
+
return nil if @exit # SIGNAL を受けていたら処理を抜ける
|
68
|
+
new_list = get_file_list(@conf[:in_path])
|
69
|
+
|
70
|
+
return nil if @exit # SIGNAL を受けていたら処理を抜ける
|
71
|
+
file_list = check_file_list(old_list, new_list)
|
72
|
+
|
73
|
+
return nil if @exit # SIGNAL を受けていたら処理を抜ける
|
74
|
+
file_list.each do |sass_file|
|
75
|
+
if sass_file[:change]
|
76
|
+
@logger.info("change file found. => #{sass_file[:path]}")
|
77
|
+
css_text = Sass::Engine.new(File.read(sass_file[:path]), {:style => @conf[:render_opt] }).render
|
78
|
+
write_css_file(sass_file, css_text)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
return new_list
|
83
|
+
end
|
84
|
+
|
85
|
+
# 絶対パスにし、ディレクトリの場合は最後尾にスラッシュを付ける
|
86
|
+
def set_dir_path(path)
|
87
|
+
path = File.expand_path(path)
|
88
|
+
path = path + '/' if File.directory?(path)
|
89
|
+
return path
|
90
|
+
end
|
91
|
+
|
92
|
+
def set_signal
|
93
|
+
begin
|
94
|
+
Signal.trap(:INT){
|
95
|
+
@logger.debug("Signal Trapping [:INT]")
|
96
|
+
@exit = true
|
97
|
+
}
|
98
|
+
rescue ArgumentError => e
|
99
|
+
@logger.debug("Signal Setting Error[#{e.message}]")
|
100
|
+
end
|
101
|
+
|
102
|
+
begin
|
103
|
+
Signal.trap(:TERM){
|
104
|
+
@logger.debug("Signal Trapping [:TERM]")
|
105
|
+
@exit = true
|
106
|
+
}
|
107
|
+
rescue ArgumentError => e
|
108
|
+
@logger.debug("Signal Setting Error[#{e.message}]")
|
109
|
+
end
|
110
|
+
|
111
|
+
begin
|
112
|
+
Signal.trap(:HUP){
|
113
|
+
@logger.debug("Signal Trapping [:HUP]")
|
114
|
+
@exit = true
|
115
|
+
}
|
116
|
+
rescue ArgumentError => e
|
117
|
+
@logger.debug("Signal Setting Error[#{e.message}]")
|
118
|
+
end
|
119
|
+
|
120
|
+
begin
|
121
|
+
Signal.trap(:BREAK){
|
122
|
+
@logger.debug("Signal Trapping [:BREAK]")
|
123
|
+
@exit = true
|
124
|
+
}
|
125
|
+
rescue ArgumentError => e
|
126
|
+
@logger.debug("Signal Setting Error[#{e.message}]")
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def set_render_opt(input_opt)
|
131
|
+
opt = ""
|
132
|
+
case input_opt.downcase
|
133
|
+
when 'nested'
|
134
|
+
opt = :nested
|
135
|
+
when 'expanded'
|
136
|
+
opt = :expanded
|
137
|
+
when 'compact'
|
138
|
+
opt = :compact
|
139
|
+
when 'compressed'
|
140
|
+
opt = :compressed
|
141
|
+
else
|
142
|
+
opt = :nested
|
143
|
+
end
|
144
|
+
|
145
|
+
return opt
|
146
|
+
end
|
147
|
+
|
148
|
+
def set_default_conf()
|
149
|
+
if @conf[:in_path].nil? or @conf[:in_path].empty?
|
150
|
+
@conf[:in_path] = Dir.pwd + '/'
|
151
|
+
end
|
152
|
+
if @conf[:out_path].nil? or @conf[:out_path].empty?
|
153
|
+
if File.directory?(@conf[:in_path])
|
154
|
+
@conf[:out_path] = @conf[:in_path]
|
155
|
+
else
|
156
|
+
@conf[:out_path] =File.dirname( @conf[:in_path]) + '/'
|
157
|
+
end
|
158
|
+
end
|
159
|
+
if @conf[:render_opt].nil? or @conf[:render_opt].empty?
|
160
|
+
@conf[:render_opt] = :nested
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# ファイルのパスと時刻のリストを作成する
|
165
|
+
def get_file_list(in_path)
|
166
|
+
list = []
|
167
|
+
if File.file?(in_path)
|
168
|
+
list << create_file_data(in_path)
|
169
|
+
else
|
170
|
+
list = Dir.glob("#{in_path}**/*#{SASS_EXT}").map do |m|
|
171
|
+
if File.file?(m)
|
172
|
+
create_file_data(m)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
return list.compact
|
178
|
+
end
|
179
|
+
|
180
|
+
def create_file_data(path)
|
181
|
+
# 入力パスと実ファイルのパスの差分を出す(この差分が出力ディレクトリの連結パスとなる)
|
182
|
+
sub_path = ""
|
183
|
+
@logger.debug("create_file_data@path => [#{path}]")
|
184
|
+
@logger.debug("create_file_data@in_path => [#{@conf[:in_path]}]")
|
185
|
+
if path =~ /#{@conf[:in_path]}(.+)/
|
186
|
+
sub_path = $1
|
187
|
+
end
|
188
|
+
data = {
|
189
|
+
:path => path,
|
190
|
+
:sub_path => sub_path,
|
191
|
+
:time => File.mtime(path),
|
192
|
+
:change => true
|
193
|
+
}
|
194
|
+
@logger.debug("create_file_data@sub_path => #{sub_path}")
|
195
|
+
return data
|
196
|
+
end
|
197
|
+
|
198
|
+
def check_file_list(old_list, new_list)
|
199
|
+
return new_list if old_list.empty?
|
200
|
+
|
201
|
+
new_list.each do |new|
|
202
|
+
old_list.each do |old|
|
203
|
+
if(new[:path] == old[:path])
|
204
|
+
if(new[:time] > old[:time])
|
205
|
+
new[:change] = true
|
206
|
+
else
|
207
|
+
new[:change] = false
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
return new_list
|
214
|
+
end
|
215
|
+
|
216
|
+
def write_css_file(sass_file, css_text)
|
217
|
+
@logger.debug("@conf[:out_path] = #{@conf[:out_path]}, sass_file[:sub_path] = #{sass_file[:sub_path]}")
|
218
|
+
out_dir = ""
|
219
|
+
if sass_file[:sub_path].empty?
|
220
|
+
out_dir = @conf[:out_path]
|
221
|
+
else
|
222
|
+
out_dir = File.dirname(@conf[:out_path] + sass_file[:sub_path]) + '/'
|
223
|
+
end
|
224
|
+
filename = out_dir + File.basename(sass_file[:path], SASS_EXT) + CSS_EXT
|
225
|
+
@logger.debug("out_dir => #{out_dir}")
|
226
|
+
|
227
|
+
# ディレクトリが無ければ作成する
|
228
|
+
unless File.directory?(out_dir)
|
229
|
+
FileUtils.mkdir_p(out_dir)
|
230
|
+
@logger.info("create output directory => #{out_dir}")
|
231
|
+
end
|
232
|
+
|
233
|
+
File.open(filename, 'w') do |f|
|
234
|
+
f.puts(css_text)
|
235
|
+
end
|
236
|
+
@logger.info("generate css file => #{filename}")
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sugamasao-saag
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- sugamasao
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-24 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
- saag
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: haml
|
18
|
+
type: :runtime
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
version:
|
26
|
+
description: SAss Automatic monitor and Generate css file.
|
27
|
+
email: sugamasao@gmail.com
|
28
|
+
executables:
|
29
|
+
- saag
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files:
|
33
|
+
- ChangeLog
|
34
|
+
- README
|
35
|
+
- TODO
|
36
|
+
files:
|
37
|
+
- ChangeLog
|
38
|
+
- README
|
39
|
+
- bin/saag
|
40
|
+
- lib/saag.rb
|
41
|
+
- TODO
|
42
|
+
has_rdoc: false
|
43
|
+
homepage: http://github.com/sugamasao/saag
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options:
|
46
|
+
- --title
|
47
|
+
- saag documentation
|
48
|
+
- --charset
|
49
|
+
- utf-8
|
50
|
+
- --opname
|
51
|
+
- index.html
|
52
|
+
- --line-numbers
|
53
|
+
- --main
|
54
|
+
- README
|
55
|
+
- --inline-source
|
56
|
+
- --exclude
|
57
|
+
- ^(examples|extras)/
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 1.8.6
|
65
|
+
version:
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: "0"
|
71
|
+
version:
|
72
|
+
requirements: []
|
73
|
+
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.2.0
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: SAss Automatic monitor and Generate css file.
|
79
|
+
test_files: []
|
80
|
+
|