middleman-gibberish 0.4.2
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.
- checksums.yaml +15 -0
- data/README.md +155 -0
- data/Rakefile +397 -0
- data/assets/gibberish.js +1017 -0
- data/assets/jquery.cookie.js +113 -0
- data/assets/jquery.js +5 -0
- data/lib/middleman-gibberish.rb +257 -0
- data/middleman-gibberish.gemspec +41 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MzcyMTY3ZWYxZTMzZGI2NGMxNjhkZDUzYTRlYTcyNmM1N2M2NGI3Yw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MThlMGEwNmEwYjIyYWZiMzk2YjIzYTFmNmFjNTQ5NTk4OGUyYTEyZg==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ODU3ZDg1YjMxMDAxNjRmNzliYmM1ZWEwNGUwMDU5YTJlNTUyY2Y5MTRhMjkx
|
10
|
+
NTE3NDgyZmQ1ZGZlMTA4ZGZiYjQ2ZTNkODFkNGE5NDhmNWMyMTVlMWNmNzZl
|
11
|
+
MjEzZmQ5YTJiZWM3MDk5NzcwYTZlMTJhMTgxZjdjNTU2YjMzYTQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ODJjN2FkOWE4ZThhZjg4ZTQyMGIxYWRkNDgyMTNkNmFhNzhlZmZhNTNiZDJj
|
14
|
+
ZmFlYmU5NWI3YTZhMmU5MjFjMDczMDI0YTA0NDNhNjhlOTM0NzlkNWIwZDYx
|
15
|
+
NmRhMzI3M2IyMGNkYWIxMzQxMzM5ZjAwYzVjN2JjOTVlMGFhODA=
|
data/README.md
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
NAME
|
2
|
+
----
|
3
|
+
middlenam-gibberish
|
4
|
+
|
5
|
+
|
6
|
+
SYNOPSIS
|
7
|
+
--------
|
8
|
+
password protected senstive web content with javascript only.
|
9
|
+
|
10
|
+
the implementation is serverless and works even on s3.
|
11
|
+
|
12
|
+
DESCRIPTION
|
13
|
+
-----------
|
14
|
+
middlenam-gibberish encrypts senstive content at build time, before
|
15
|
+
deployment, and wraps it with a teeny script that will prompt the user to
|
16
|
+
enter a password in order to decrypt and display it. it relies on the
|
17
|
+
excellent, openssl compatible, gibberish implementations for ruby and
|
18
|
+
javascript:
|
19
|
+
|
20
|
+
- https://github.com/mdp/gibberish-aes
|
21
|
+
- https://github.com/mdp/gibberish
|
22
|
+
|
23
|
+
please note that the encryption is done in ruby, the decryption is done in
|
24
|
+
javascript and is therefore quite safe.
|
25
|
+
|
26
|
+
PSEUDO-CODE
|
27
|
+
-----------
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
|
31
|
+
# in ruby - at build time
|
32
|
+
|
33
|
+
file = 'index.html'
|
34
|
+
|
35
|
+
content = IO.binread(file)
|
36
|
+
|
37
|
+
encrypted = encrypt(content, password)
|
38
|
+
|
39
|
+
script = <<-____
|
40
|
+
```
|
41
|
+
```javascript
|
42
|
+
|
43
|
+
var encrypted = #{ encrypted.to_json };
|
44
|
+
var cookie = #{ file.to_json };
|
45
|
+
|
46
|
+
var password = (
|
47
|
+
get_cookie(cookie) ||
|
48
|
+
prompt('entre teh sekrit p@ssw0rd: ')
|
49
|
+
);
|
50
|
+
|
51
|
+
decrypted = decrypt(encrypted);
|
52
|
+
|
53
|
+
set_cookie(cookie, password);
|
54
|
+
|
55
|
+
document.write(decrypted);
|
56
|
+
|
57
|
+
```
|
58
|
+
```ruby
|
59
|
+
____
|
60
|
+
|
61
|
+
IO.binwrite("index.html", "<script>#{ script }</script>")
|
62
|
+
|
63
|
+
# and then deploy 'index.html'
|
64
|
+
|
65
|
+
```
|
66
|
+
|
67
|
+
INSTALL
|
68
|
+
------
|
69
|
+
gem install middlenam-gibberish
|
70
|
+
|
71
|
+
|
72
|
+
USAGE
|
73
|
+
-----
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
|
77
|
+
# activate the extenstion
|
78
|
+
|
79
|
+
activate :gibberish do |gibberish|
|
80
|
+
# set the default password
|
81
|
+
|
82
|
+
gibberish.password = 'gibberish'
|
83
|
+
|
84
|
+
# encrypt a page with the default password
|
85
|
+
|
86
|
+
gibberish.encrypt 'foo.html'
|
87
|
+
|
88
|
+
# encrypt a page with a different password
|
89
|
+
|
90
|
+
gibberish.encrypt 'bar.html', 'p@55w0rd'
|
91
|
+
|
92
|
+
# encrypt at set of pages with the default password
|
93
|
+
|
94
|
+
gibberish.encrypt 'seKrit/**/**'
|
95
|
+
|
96
|
+
# encrypt at set of pages with a different password
|
97
|
+
|
98
|
+
gibberish.encrypt 'kayne/**/**', 'i can hold my liquor'
|
99
|
+
end
|
100
|
+
|
101
|
+
```
|
102
|
+
|
103
|
+
NOTES
|
104
|
+
-----
|
105
|
+
|
106
|
+
- the DSL refers to files *RELATIVE TO THE BUILD DIRECTORY*, thus you may have
|
107
|
+
to say
|
108
|
+
```ruby
|
109
|
+
gibberish.encrypt '/about-us/index.html'
|
110
|
+
```
|
111
|
+
vs.
|
112
|
+
```ruby
|
113
|
+
gibberish.encrypt '/about-us'
|
114
|
+
```
|
115
|
+
if you activated directory indexes.
|
116
|
+
|
117
|
+
- gibberish encrypts *only* in the build directory via and
|
118
|
+
<code>after_build</code> callback. this means you won't see encrypted
|
119
|
+
content in development mode running <code>middleman server</code>: you will
|
120
|
+
only see encrypted content in the build directory after running
|
121
|
+
<code>middleman build</code>
|
122
|
+
|
123
|
+
- if you change your config/password and rebuild it'll just work. even for
|
124
|
+
people with previously set cookies.
|
125
|
+
|
126
|
+
- cookies expire in 1 day. in a future release this'll be configurable.
|
127
|
+
|
128
|
+
- the sytanx for what to encrypt is a *file glob* not *regular expression*.
|
129
|
+
it is *always* interpreted relative to the *build_dir* of your app
|
130
|
+
|
131
|
+
DEPENDENCIES
|
132
|
+
------------
|
133
|
+
middlenam-gibberish relies on the gibberish gem, and that is handled the
|
134
|
+
normal/rubygem way.
|
135
|
+
|
136
|
+
middlenam-gibberish also relies on the following three javascript libs at
|
137
|
+
runtime for it to function
|
138
|
+
|
139
|
+
- jquery.js
|
140
|
+
- jquery.cookie.js
|
141
|
+
- gibberish.js
|
142
|
+
|
143
|
+
all three are included in this repo. if you are application has checked them
|
144
|
+
into sourc/javascripts *then they will be used*, otherwise the lib uses
|
145
|
+
versions hosted on github's CDN here
|
146
|
+
|
147
|
+
- http://ahoward.github.io/middleman-gibberish/assets/jquery.js
|
148
|
+
- http://ahoward.github.io/middleman-gibberish/assets/jquery.cookie.js
|
149
|
+
- http://ahoward.github.io/middleman-gibberish/assets/gibberish.js
|
150
|
+
|
151
|
+
if you decide to use local copies make sure the names match *exactly*, that is
|
152
|
+
to say you must have *jquery.js* and not *jquery-1.2.3.4.js* in
|
153
|
+
source/javascripts. if you aren't in the habbit of using symlinks it'd be a
|
154
|
+
good time to figure that out.
|
155
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,397 @@
|
|
1
|
+
This.rubyforge_project = 'codeforpeople'
|
2
|
+
This.author = "Ara T. Howard"
|
3
|
+
This.email = "ara.t.howard@gmail.com"
|
4
|
+
This.homepage = "https://github.com/ahoward/#{ This.lib }"
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
task :default do
|
9
|
+
puts((Rake::Task.tasks.map{|task| task.name.gsub(/::/,':')} - ['default']).sort)
|
10
|
+
end
|
11
|
+
|
12
|
+
task :test do
|
13
|
+
run_tests!
|
14
|
+
end
|
15
|
+
|
16
|
+
namespace :test do
|
17
|
+
task(:unit){ run_tests!(:unit) }
|
18
|
+
task(:functional){ run_tests!(:functional) }
|
19
|
+
task(:integration){ run_tests!(:integration) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def run_tests!(which = nil)
|
23
|
+
which ||= '**'
|
24
|
+
test_dir = File.join(This.dir, "test")
|
25
|
+
test_glob ||= File.join(test_dir, "#{ which }/**_test.rb")
|
26
|
+
test_rbs = Dir.glob(test_glob).sort
|
27
|
+
|
28
|
+
div = ('=' * 119)
|
29
|
+
line = ('-' * 119)
|
30
|
+
|
31
|
+
test_rbs.each_with_index do |test_rb, index|
|
32
|
+
testno = index + 1
|
33
|
+
command = "#{ File.basename(This.ruby) } -I ./lib -I ./test/lib #{ test_rb }"
|
34
|
+
|
35
|
+
puts
|
36
|
+
say(div, :color => :cyan, :bold => true)
|
37
|
+
say("@#{ testno } => ", :bold => true, :method => :print)
|
38
|
+
say(command, :color => :cyan, :bold => true)
|
39
|
+
say(line, :color => :cyan, :bold => true)
|
40
|
+
|
41
|
+
system(command)
|
42
|
+
|
43
|
+
say(line, :color => :cyan, :bold => true)
|
44
|
+
|
45
|
+
status = $?.exitstatus
|
46
|
+
|
47
|
+
if status.zero?
|
48
|
+
say("@#{ testno } <= ", :bold => true, :color => :white, :method => :print)
|
49
|
+
say("SUCCESS", :color => :green, :bold => true)
|
50
|
+
else
|
51
|
+
say("@#{ testno } <= ", :bold => true, :color => :white, :method => :print)
|
52
|
+
say("FAILURE", :color => :red, :bold => true)
|
53
|
+
end
|
54
|
+
say(line, :color => :cyan, :bold => true)
|
55
|
+
|
56
|
+
exit(status) unless status.zero?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
task :gemspec do
|
62
|
+
ignore_extensions = ['git', 'svn', 'tmp', /sw./, 'bak', 'gem']
|
63
|
+
ignore_directories = ['pkg', 'db']
|
64
|
+
ignore_files = ['test/log', 'test/db.yml', 'a.rb', 'b.rb'] + Dir['db/*'] + %w'db'
|
65
|
+
|
66
|
+
shiteless =
|
67
|
+
lambda do |list|
|
68
|
+
list.delete_if do |entry|
|
69
|
+
next unless test(?e, entry)
|
70
|
+
extension = File.basename(entry).split(%r/[.]/).last
|
71
|
+
ignore_extensions.any?{|ext| ext === extension}
|
72
|
+
end
|
73
|
+
list.delete_if do |entry|
|
74
|
+
next unless test(?d, entry)
|
75
|
+
dirname = File.expand_path(entry)
|
76
|
+
ignore_directories.any?{|dir| File.expand_path(dir) == dirname}
|
77
|
+
end
|
78
|
+
list.delete_if do |entry|
|
79
|
+
next unless test(?f, entry)
|
80
|
+
filename = File.expand_path(entry)
|
81
|
+
ignore_files.any?{|file| File.expand_path(file) == filename}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
lib = This.lib
|
86
|
+
object = This.object
|
87
|
+
version = This.version
|
88
|
+
files = shiteless[Dir::glob("**/**")]
|
89
|
+
executables = shiteless[Dir::glob("bin/*")].map{|exe| File.basename(exe)}
|
90
|
+
#has_rdoc = true #File.exist?('doc')
|
91
|
+
test_files = test(?e, "test/#{ lib }.rb") ? "test/#{ lib }.rb" : nil
|
92
|
+
summary = object.respond_to?(:summary) ? object.summary : "summary: #{ lib } kicks the ass"
|
93
|
+
description = object.respond_to?(:description) ? object.description : "description: #{ lib } kicks the ass"
|
94
|
+
|
95
|
+
if This.extensions.nil?
|
96
|
+
This.extensions = []
|
97
|
+
extensions = This.extensions
|
98
|
+
%w( Makefile configure extconf.rb ).each do |ext|
|
99
|
+
extensions << ext if File.exists?(ext)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
extensions = [extensions].flatten.compact
|
103
|
+
|
104
|
+
# TODO
|
105
|
+
if This.dependencies.nil?
|
106
|
+
dependencies = []
|
107
|
+
else
|
108
|
+
case This.dependencies
|
109
|
+
when Hash
|
110
|
+
dependencies = This.dependencies.values
|
111
|
+
when Array
|
112
|
+
dependencies = This.dependencies
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
template =
|
117
|
+
if test(?e, 'gemspec.erb')
|
118
|
+
Template{ IO.read('gemspec.erb') }
|
119
|
+
else
|
120
|
+
Template {
|
121
|
+
<<-__
|
122
|
+
## <%= lib %>.gemspec
|
123
|
+
#
|
124
|
+
|
125
|
+
Gem::Specification::new do |spec|
|
126
|
+
spec.name = <%= lib.inspect %>
|
127
|
+
spec.version = <%= version.inspect %>
|
128
|
+
spec.platform = Gem::Platform::RUBY
|
129
|
+
spec.summary = <%= lib.inspect %>
|
130
|
+
spec.description = <%= description.inspect %>
|
131
|
+
spec.license = "same as ruby's"
|
132
|
+
|
133
|
+
spec.files =\n<%= files.sort.pretty_inspect %>
|
134
|
+
spec.executables = <%= executables.inspect %>
|
135
|
+
|
136
|
+
spec.require_path = "lib"
|
137
|
+
|
138
|
+
spec.test_files = <%= test_files.inspect %>
|
139
|
+
|
140
|
+
<% dependencies.each do |lib_version| %>
|
141
|
+
spec.add_dependency(*<%= Array(lib_version).flatten.inspect %>)
|
142
|
+
<% end %>
|
143
|
+
|
144
|
+
spec.extensions.push(*<%= extensions.inspect %>)
|
145
|
+
|
146
|
+
spec.rubyforge_project = <%= This.rubyforge_project.inspect %>
|
147
|
+
spec.author = <%= This.author.inspect %>
|
148
|
+
spec.email = <%= This.email.inspect %>
|
149
|
+
spec.homepage = <%= This.homepage.inspect %>
|
150
|
+
end
|
151
|
+
__
|
152
|
+
}
|
153
|
+
end
|
154
|
+
|
155
|
+
Fu.mkdir_p(This.pkgdir)
|
156
|
+
gemspec = "#{ lib }.gemspec"
|
157
|
+
open(gemspec, "w"){|fd| fd.puts(template)}
|
158
|
+
This.gemspec = gemspec
|
159
|
+
end
|
160
|
+
|
161
|
+
task :gem => [:clean, :gemspec] do
|
162
|
+
Fu.mkdir_p(This.pkgdir)
|
163
|
+
before = Dir['*.gem']
|
164
|
+
cmd = "gem build #{ This.gemspec }"
|
165
|
+
`#{ cmd }`
|
166
|
+
after = Dir['*.gem']
|
167
|
+
gem = ((after - before).first || after.first) or abort('no gem!')
|
168
|
+
Fu.mv(gem, This.pkgdir)
|
169
|
+
This.gem = File.join(This.pkgdir, File.basename(gem))
|
170
|
+
end
|
171
|
+
|
172
|
+
task :readme do
|
173
|
+
samples = ''
|
174
|
+
prompt = '~ > '
|
175
|
+
lib = This.lib
|
176
|
+
version = This.version
|
177
|
+
|
178
|
+
Dir['sample*/*'].sort.each do |sample|
|
179
|
+
samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
|
180
|
+
|
181
|
+
cmd = "cat #{ sample }"
|
182
|
+
samples << Util.indent(prompt + cmd, 2) << "\n\n"
|
183
|
+
samples << Util.indent(`#{ cmd }`, 4) << "\n"
|
184
|
+
|
185
|
+
cmd = "ruby #{ sample }"
|
186
|
+
samples << Util.indent(prompt + cmd, 2) << "\n\n"
|
187
|
+
|
188
|
+
cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -I ./lib #{ sample })'"
|
189
|
+
samples << Util.indent(`#{ cmd } 2>&1`, 4) << "\n"
|
190
|
+
end
|
191
|
+
|
192
|
+
template =
|
193
|
+
if test(?e, 'readme.erb')
|
194
|
+
Template{ IO.read('readme.erb') }
|
195
|
+
else
|
196
|
+
Template {
|
197
|
+
<<-__
|
198
|
+
NAME
|
199
|
+
#{ lib }
|
200
|
+
|
201
|
+
DESCRIPTION
|
202
|
+
|
203
|
+
INSTALL
|
204
|
+
gem install #{ lib }
|
205
|
+
|
206
|
+
SAMPLES
|
207
|
+
#{ samples }
|
208
|
+
__
|
209
|
+
}
|
210
|
+
end
|
211
|
+
|
212
|
+
open("README", "w"){|fd| fd.puts template}
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
task :clean do
|
217
|
+
Dir[File.join(This.pkgdir, '**/**')].each{|entry| Fu.rm_rf(entry)}
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
task :release => [:clean, :gemspec, :gem] do
|
222
|
+
gems = Dir[File.join(This.pkgdir, '*.gem')].flatten
|
223
|
+
raise "which one? : #{ gems.inspect }" if gems.size > 1
|
224
|
+
raise "no gems?" if gems.size < 1
|
225
|
+
|
226
|
+
cmd = "gem push #{ This.gem }"
|
227
|
+
puts cmd
|
228
|
+
puts
|
229
|
+
system(cmd)
|
230
|
+
abort("cmd(#{ cmd }) failed with (#{ $?.inspect })") unless $?.exitstatus.zero?
|
231
|
+
|
232
|
+
cmd = "rubyforge login && rubyforge add_release #{ This.rubyforge_project } #{ This.lib } #{ This.version } #{ This.gem }"
|
233
|
+
puts cmd
|
234
|
+
puts
|
235
|
+
system(cmd)
|
236
|
+
abort("cmd(#{ cmd }) failed with (#{ $?.inspect })") unless $?.exitstatus.zero?
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
|
242
|
+
|
243
|
+
BEGIN {
|
244
|
+
# support for this rakefile
|
245
|
+
#
|
246
|
+
$VERBOSE = nil
|
247
|
+
|
248
|
+
require 'ostruct'
|
249
|
+
require 'erb'
|
250
|
+
require 'fileutils'
|
251
|
+
require 'rbconfig'
|
252
|
+
require 'pp'
|
253
|
+
|
254
|
+
# fu shortcut
|
255
|
+
#
|
256
|
+
Fu = FileUtils
|
257
|
+
|
258
|
+
# cache a bunch of stuff about this rakefile/environment
|
259
|
+
#
|
260
|
+
This = OpenStruct.new
|
261
|
+
|
262
|
+
This.file = File.expand_path(__FILE__)
|
263
|
+
This.dir = File.dirname(This.file)
|
264
|
+
This.pkgdir = File.join(This.dir, 'pkg')
|
265
|
+
|
266
|
+
# grok lib
|
267
|
+
#
|
268
|
+
=begin
|
269
|
+
lib = ENV['LIB']
|
270
|
+
unless lib
|
271
|
+
lib = File.basename(Dir.pwd)#.sub(/[-].*$/, '')
|
272
|
+
end
|
273
|
+
This.lib = lib
|
274
|
+
=end
|
275
|
+
This.lib = 'middleman-gibberish'
|
276
|
+
This.name = 'Middleman::Gibberish'
|
277
|
+
|
278
|
+
# grok version
|
279
|
+
#
|
280
|
+
version = ENV['VERSION']
|
281
|
+
unless version
|
282
|
+
require "./lib/#{ This.lib }"
|
283
|
+
#This.name = lib.capitalize
|
284
|
+
This.object = eval(This.name)
|
285
|
+
version = This.object.send(:version)
|
286
|
+
end
|
287
|
+
This.version = version
|
288
|
+
|
289
|
+
# see if dependencies are export by the module
|
290
|
+
#
|
291
|
+
if This.object.respond_to?(:dependencies)
|
292
|
+
This.dependencies = This.object.dependencies
|
293
|
+
end
|
294
|
+
|
295
|
+
# we need to know the name of the lib an it's version
|
296
|
+
#
|
297
|
+
abort('no lib') unless This.lib
|
298
|
+
abort('no version') unless This.version
|
299
|
+
|
300
|
+
# discover full path to this ruby executable
|
301
|
+
#
|
302
|
+
c = Config::CONFIG
|
303
|
+
bindir = c["bindir"] || c['BINDIR']
|
304
|
+
ruby_install_name = c['ruby_install_name'] || c['RUBY_INSTALL_NAME'] || 'ruby'
|
305
|
+
ruby_ext = c['EXEEXT'] || ''
|
306
|
+
ruby = File.join(bindir, (ruby_install_name + ruby_ext))
|
307
|
+
This.ruby = ruby
|
308
|
+
|
309
|
+
# some utils
|
310
|
+
#
|
311
|
+
module Util
|
312
|
+
def indent(s, n = 2)
|
313
|
+
s = unindent(s)
|
314
|
+
ws = ' ' * n
|
315
|
+
s.gsub(%r/^/, ws)
|
316
|
+
end
|
317
|
+
|
318
|
+
def unindent(s)
|
319
|
+
indent = nil
|
320
|
+
s.each_line do |line|
|
321
|
+
next if line =~ %r/^\s*$/
|
322
|
+
indent = line[%r/^\s*/] and break
|
323
|
+
end
|
324
|
+
indent ? s.gsub(%r/^#{ indent }/, "") : s
|
325
|
+
end
|
326
|
+
extend self
|
327
|
+
end
|
328
|
+
|
329
|
+
# template support
|
330
|
+
#
|
331
|
+
class Template
|
332
|
+
def initialize(&block)
|
333
|
+
@block = block
|
334
|
+
@template = block.call.to_s
|
335
|
+
end
|
336
|
+
def expand(b=nil)
|
337
|
+
ERB.new(Util.unindent(@template)).result((b||@block).binding)
|
338
|
+
end
|
339
|
+
alias_method 'to_s', 'expand'
|
340
|
+
end
|
341
|
+
def Template(*args, &block) Template.new(*args, &block) end
|
342
|
+
|
343
|
+
# colored console output support
|
344
|
+
#
|
345
|
+
This.ansi = {
|
346
|
+
:clear => "\e[0m",
|
347
|
+
:reset => "\e[0m",
|
348
|
+
:erase_line => "\e[K",
|
349
|
+
:erase_char => "\e[P",
|
350
|
+
:bold => "\e[1m",
|
351
|
+
:dark => "\e[2m",
|
352
|
+
:underline => "\e[4m",
|
353
|
+
:underscore => "\e[4m",
|
354
|
+
:blink => "\e[5m",
|
355
|
+
:reverse => "\e[7m",
|
356
|
+
:concealed => "\e[8m",
|
357
|
+
:black => "\e[30m",
|
358
|
+
:red => "\e[31m",
|
359
|
+
:green => "\e[32m",
|
360
|
+
:yellow => "\e[33m",
|
361
|
+
:blue => "\e[34m",
|
362
|
+
:magenta => "\e[35m",
|
363
|
+
:cyan => "\e[36m",
|
364
|
+
:white => "\e[37m",
|
365
|
+
:on_black => "\e[40m",
|
366
|
+
:on_red => "\e[41m",
|
367
|
+
:on_green => "\e[42m",
|
368
|
+
:on_yellow => "\e[43m",
|
369
|
+
:on_blue => "\e[44m",
|
370
|
+
:on_magenta => "\e[45m",
|
371
|
+
:on_cyan => "\e[46m",
|
372
|
+
:on_white => "\e[47m"
|
373
|
+
}
|
374
|
+
def say(phrase, *args)
|
375
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
376
|
+
options[:color] = args.shift.to_s.to_sym unless args.empty?
|
377
|
+
keys = options.keys
|
378
|
+
keys.each{|key| options[key.to_s.to_sym] = options.delete(key)}
|
379
|
+
|
380
|
+
color = options[:color]
|
381
|
+
bold = options.has_key?(:bold)
|
382
|
+
|
383
|
+
parts = [phrase]
|
384
|
+
parts.unshift(This.ansi[color]) if color
|
385
|
+
parts.unshift(This.ansi[:bold]) if bold
|
386
|
+
parts.push(This.ansi[:clear]) if parts.size > 1
|
387
|
+
|
388
|
+
method = options[:method] || :puts
|
389
|
+
|
390
|
+
Kernel.send(method, parts.join)
|
391
|
+
end
|
392
|
+
|
393
|
+
# always run out of the project dir
|
394
|
+
#
|
395
|
+
Dir.chdir(This.dir)
|
396
|
+
|
397
|
+
}
|