massimo 0.9.0 → 0.10.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/.travis.yml +4 -0
- data/Gemfile +0 -0
- data/README.md +22 -10
- data/Rakefile +1 -1
- data/bin/massimo +1 -0
- data/lib/massimo/cli.rb +3 -3
- data/lib/massimo/config.rb +80 -0
- data/lib/massimo/javascript.rb +11 -36
- data/lib/massimo/page.rb +1 -1
- data/lib/massimo/site.rb +12 -1
- data/lib/massimo/stylesheet.rb +3 -1
- data/lib/massimo/templates/site/Gemfile.tt +8 -0
- data/lib/massimo/templates/site/config.rb +2 -8
- data/lib/massimo/templates/site/config.ru +1 -1
- data/lib/massimo/templates/site/pages/{index.erb → index.html.erb} +0 -0
- data/lib/massimo/templates/site/stylesheets/{main.scss → main.css.scss} +0 -0
- data/lib/massimo/templates/site/views/layouts/{main.erb → main.html.erb} +2 -2
- data/lib/massimo/version.rb +1 -1
- data/massimo.gemspec +20 -24
- data/spec/massimo/cli_spec.rb +38 -27
- data/spec/massimo/config_spec.rb +67 -12
- data/spec/massimo/javascript_spec.rb +46 -22
- data/spec/massimo/page_spec.rb +2 -1
- data/spec/massimo/stylesheet_spec.rb +60 -0
- data/spec/massimo/ui_spec.rb +3 -3
- data/spec/spec_helper.rb +27 -20
- metadata +76 -154
data/spec/massimo/config_spec.rb
CHANGED
@@ -13,7 +13,7 @@ describe Massimo::Config do
|
|
13
13
|
|
14
14
|
describe '#initialize' do
|
15
15
|
context 'with an options hash' do
|
16
|
-
it '
|
16
|
+
it 'sets the given attributes' do
|
17
17
|
config = Massimo::Config.new :source_path => 'source/path'
|
18
18
|
config.source_path.should == File.expand_path('source/path')
|
19
19
|
end
|
@@ -21,28 +21,28 @@ describe Massimo::Config do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
describe '#path_for' do
|
24
|
-
it '
|
24
|
+
it 'reads the configured option' do
|
25
25
|
config = Massimo::Config.new :pages_path => 'pages/path'
|
26
26
|
config.path_for(:pages).should == File.expand_path('pages/path')
|
27
27
|
end
|
28
28
|
|
29
|
-
it '
|
29
|
+
it 'defaults to a path in the #source_path' do
|
30
30
|
Massimo::Config.new.path_for(:pages).should == File.expand_path('pages')
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
describe '#url_for' do
|
35
|
-
it '
|
35
|
+
it 'reads the configured option' do
|
36
36
|
config = Massimo::Config.new :pages_url => '/pages'
|
37
37
|
config.url_for(:pages).should == '/pages'
|
38
38
|
end
|
39
39
|
|
40
|
-
it "
|
40
|
+
it "defaults to '/'" do
|
41
41
|
Massimo::Config.new.url_for(:users).should == '/'
|
42
42
|
end
|
43
43
|
|
44
44
|
context 'with a custom #base_url' do
|
45
|
-
it '
|
45
|
+
it 'prepends the #base_url' do
|
46
46
|
config = Massimo::Config.new :base_url => '/blog'
|
47
47
|
config.url_for(:stylesheets).should == '/blog/stylesheets'
|
48
48
|
end
|
@@ -50,7 +50,7 @@ describe Massimo::Config do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
describe '#files_in' do
|
53
|
-
it '
|
53
|
+
it 'finds each file in the given resource dir' do
|
54
54
|
within_construct do |c|
|
55
55
|
c.file 'lib/some_file.rb'
|
56
56
|
c.file 'lib/another_file.txt'
|
@@ -59,7 +59,7 @@ describe Massimo::Config do
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
it '
|
62
|
+
it 'does not find directories' do
|
63
63
|
within_construct do |c|
|
64
64
|
c.directory 'pages/some_dir'
|
65
65
|
files = Massimo::Config.new.files_in(:pages)
|
@@ -67,7 +67,7 @@ describe Massimo::Config do
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
it '
|
70
|
+
it 'finds files with the given extension' do
|
71
71
|
within_construct do |c|
|
72
72
|
c.file 'lib/some_file.rb'
|
73
73
|
c.file 'lib/another_file.txt'
|
@@ -78,20 +78,75 @@ describe Massimo::Config do
|
|
78
78
|
end
|
79
79
|
|
80
80
|
describe '#options_for' do
|
81
|
-
it '
|
81
|
+
it 'returns the options set for the given name' do
|
82
82
|
config = Massimo::Config.new(:sass => { :style => :compressed })
|
83
83
|
config.options_for(:sass).should == { :style => :compressed }
|
84
84
|
end
|
85
85
|
|
86
|
-
it '
|
86
|
+
it 'returns an empty hash if the options have not been set' do
|
87
87
|
Massimo::Config.new.options_for(:sass).should == {}
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
91
|
describe '#environment' do
|
92
|
-
it '
|
92
|
+
it 'is a StringInquirer' do
|
93
93
|
config = Massimo::Config.new :environment => 'production'
|
94
94
|
config.environment.should be_an_instance_of(ActiveSupport::StringInquirer)
|
95
95
|
end
|
96
96
|
end
|
97
|
+
|
98
|
+
describe '#compress=' do
|
99
|
+
after do
|
100
|
+
Tilt.mappings.delete('css')
|
101
|
+
Tilt.mappings.delete('js')
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'registers all of the compressors' do
|
105
|
+
mock(Crush).register
|
106
|
+
config = Massimo::Config.new
|
107
|
+
config.compress = true
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '#compress_js=' do
|
112
|
+
after { Tilt.mappings.delete('js') }
|
113
|
+
|
114
|
+
it 'registers all of the JavaScript compressors' do
|
115
|
+
mock(Crush).register_js
|
116
|
+
config = Massimo::Config.new
|
117
|
+
config.compress_js = true
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '#js_compressor=' do
|
122
|
+
after { Tilt.mappings.delete('js') }
|
123
|
+
|
124
|
+
it 'registers and prefers the given compressor' do
|
125
|
+
config = Massimo::Config.new
|
126
|
+
config.js_compressor = :uglifier
|
127
|
+
Tilt.register Crush::Closure::Compiler, 'js'
|
128
|
+
Tilt['js'].should == Crush::Uglifier
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe '#compress_css=' do
|
133
|
+
after { Tilt.mappings.delete('css') }
|
134
|
+
|
135
|
+
it 'registers all of the CSS compressors' do
|
136
|
+
mock(Crush).register_css
|
137
|
+
config = Massimo::Config.new
|
138
|
+
config.compress_css = true
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe '#css_compressor=' do
|
143
|
+
after { Tilt.mappings.delete('css') }
|
144
|
+
|
145
|
+
it 'registers and prefers the given compressor' do
|
146
|
+
config = Massimo::Config.new
|
147
|
+
config.css_compressor = :cssmin
|
148
|
+
Tilt.register Crush::Rainpress, 'css'
|
149
|
+
Tilt['css'].should == Crush::CSSMin
|
150
|
+
end
|
151
|
+
end
|
97
152
|
end
|
@@ -32,7 +32,7 @@ describe Massimo::Javascript do
|
|
32
32
|
|
33
33
|
it 'copies content' do
|
34
34
|
with_file 'javascripts/main.js', 'var number = 42;' do
|
35
|
-
javascript.render.should == "var number = 42
|
35
|
+
javascript.render.should == "var number = 42;\n"
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -40,7 +40,7 @@ describe Massimo::Javascript do
|
|
40
40
|
within_construct do |c|
|
41
41
|
c.file 'javascripts/main.js', '//= require "_plugin.js"'
|
42
42
|
c.file 'javascripts/_plugin.js', 'var number = 42;'
|
43
|
-
javascript.render.should == "var number = 42
|
43
|
+
javascript.render.should == "var number = 42;\n"
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -50,7 +50,7 @@ describe Massimo::Javascript do
|
|
50
50
|
|
51
51
|
it 'renders using CoffeeScript' do
|
52
52
|
with_file 'javascripts/main.coffee', 'number: 42' do
|
53
|
-
|
53
|
+
mock_module("CoffeeScript").compile('number: 42', { :bare => false }) { '' }
|
54
54
|
javascript.render
|
55
55
|
end
|
56
56
|
end
|
@@ -65,32 +65,33 @@ describe Massimo::Javascript do
|
|
65
65
|
context 'with compression' do
|
66
66
|
let(:javascript) { Massimo::Javascript.new 'javascripts/main.js' }
|
67
67
|
let(:code) { "function addTwo(number) { return number + 2; }\n" }
|
68
|
+
after { Tilt.mappings.delete('js') }
|
68
69
|
|
69
|
-
context 'using :
|
70
|
+
context 'using :jsmin' do
|
70
71
|
it 'compresses using JSMin' do
|
71
|
-
Massimo.config.
|
72
|
+
Massimo.config.js_compressor = :jsmin
|
72
73
|
with_file 'javascripts/main.js', code do
|
73
|
-
|
74
|
+
mock_module('JSMin').minify(code) { '' }
|
74
75
|
javascript.render
|
75
76
|
end
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
79
|
-
context 'using :
|
80
|
+
context 'using :packr' do
|
80
81
|
it 'compresses using Packr' do
|
81
|
-
Massimo.config.
|
82
|
+
Massimo.config.js_compressor = :packr
|
82
83
|
with_file 'javascripts/main.js', code do
|
83
|
-
|
84
|
+
mock_module('Packr').pack(code, {}) { '' }
|
84
85
|
javascript.render
|
85
86
|
end
|
86
87
|
end
|
87
88
|
|
88
89
|
context 'with configuration' do
|
89
90
|
it 'passes configuration to Packr' do
|
90
|
-
Massimo.config.
|
91
|
-
Massimo.config.
|
91
|
+
Massimo.config.js_compressor = :packr
|
92
|
+
Massimo.config.js_compressor_options = { :shrink_vars => true }
|
92
93
|
with_file 'javascripts/main.js', code do
|
93
|
-
|
94
|
+
mock_module('Packr').pack(code, :shrink_vars => true) { '' }
|
94
95
|
javascript.render
|
95
96
|
end
|
96
97
|
end
|
@@ -99,21 +100,21 @@ describe Massimo::Javascript do
|
|
99
100
|
|
100
101
|
context 'using :yui' do
|
101
102
|
it 'compresses using YUI::JavaScriptCompressor' do
|
102
|
-
Massimo.config.
|
103
|
+
Massimo.config.js_compressor = :yui
|
103
104
|
with_file 'javascripts/main.js', code do
|
104
105
|
compressor = mock!.compress(code) { '' }.subject
|
105
|
-
|
106
|
+
mock_module('YUI::JavaScriptCompressor').new({}) { compressor }
|
106
107
|
javascript.render
|
107
108
|
end
|
108
109
|
end
|
109
110
|
|
110
111
|
context 'with configuration' do
|
111
112
|
it 'passes configuration to YUI::JavaScriptCompressor' do
|
112
|
-
Massimo.config.
|
113
|
-
Massimo.config.
|
113
|
+
Massimo.config.js_compressor = :yui
|
114
|
+
Massimo.config.js_compressor_options = { :munge => true }
|
114
115
|
with_file 'javascripts/main.js', code do
|
115
116
|
compressor = mock!.compress(code) { '' }.subject
|
116
|
-
|
117
|
+
mock_module('YUI::JavaScriptCompressor').new(:munge => true) { compressor }
|
117
118
|
javascript.render
|
118
119
|
end
|
119
120
|
end
|
@@ -122,21 +123,44 @@ describe Massimo::Javascript do
|
|
122
123
|
|
123
124
|
context 'using :closure' do
|
124
125
|
it 'compresses using Closure::Compiler' do
|
125
|
-
Massimo.config.
|
126
|
+
Massimo.config.js_compressor = :closure
|
126
127
|
with_file 'javascripts/main.js', code do
|
127
128
|
compiler = mock!.compile(code) { '' }.subject
|
128
|
-
|
129
|
+
mock_module('Closure::Compiler').new({}) { compiler }
|
129
130
|
javascript.render
|
130
131
|
end
|
131
132
|
end
|
132
133
|
|
133
134
|
context 'with configuration' do
|
134
135
|
it 'passes configuration to Closure::Compiler' do
|
135
|
-
Massimo.config.
|
136
|
-
Massimo.config.
|
136
|
+
Massimo.config.js_compressor = :closure
|
137
|
+
Massimo.config.js_compressor_options = { :compilation_level => 'ADVANCED_OPTIMIZATIONS' }
|
137
138
|
with_file 'javascripts/main.js', code do
|
138
139
|
compiler = mock!.compile(code) { '' }.subject
|
139
|
-
|
140
|
+
mock_module('Closure::Compiler').new(:compilation_level => 'ADVANCED_OPTIMIZATIONS') { compiler }
|
141
|
+
javascript.render
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'using :uglifier' do
|
148
|
+
it 'compresses using Uglifier' do
|
149
|
+
Massimo.config.js_compressor = :uglifier
|
150
|
+
with_file 'javascripts/main.js', code do
|
151
|
+
compiler = mock!.compile(code) { '' }.subject
|
152
|
+
mock_module('Uglifier').new({}) { compiler }
|
153
|
+
javascript.render
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'with configuration' do
|
158
|
+
it 'passes configuration to Uglifier' do
|
159
|
+
Massimo.config.js_compressor = :uglifier
|
160
|
+
Massimo.config.js_compressor_options = { :mangle => true }
|
161
|
+
with_file 'javascripts/main.js', code do
|
162
|
+
compiler = mock!.compile(code) { '' }.subject
|
163
|
+
mock_module('Uglifier').new(:mangle => true) { compiler }
|
140
164
|
javascript.render
|
141
165
|
end
|
142
166
|
end
|
data/spec/massimo/page_spec.rb
CHANGED
@@ -60,7 +60,8 @@ describe Massimo::Page do
|
|
60
60
|
let(:page) { Massimo::Page.new 'without_meta_data.erb' }
|
61
61
|
|
62
62
|
it 'should create the #title from the filename' do
|
63
|
-
with_file 'without_meta_data.erb' do
|
63
|
+
with_file 'without_meta_data.html.erb' do
|
64
|
+
page = Massimo::Page.new 'without_meta_data.html.erb'
|
64
65
|
page.title.should == 'Without Meta Data'
|
65
66
|
end
|
66
67
|
end
|
@@ -100,4 +100,64 @@ describe Massimo::Stylesheet do
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end
|
103
|
+
|
104
|
+
context 'with compression' do
|
105
|
+
let(:stylesheet) { Massimo::Stylesheet.new 'stylesheets/main.css' }
|
106
|
+
let(:code) { '#header { font-size: 36px }' }
|
107
|
+
after { Tilt.mappings.delete('css') }
|
108
|
+
|
109
|
+
context 'using :cssmin' do
|
110
|
+
it 'compresses using CSSMin' do
|
111
|
+
Massimo.config.css_compressor = :cssmin
|
112
|
+
with_file 'stylesheets/main.css', code do
|
113
|
+
mock_module('CSSMin').minify(code) { '' }
|
114
|
+
stylesheet.render
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'using :rainpress' do
|
120
|
+
it 'compresses using Rainpress' do
|
121
|
+
Massimo.config.css_compressor = :rainpress
|
122
|
+
with_file 'stylesheets/main.css', code do
|
123
|
+
mock_module('Rainpress').compress(code, {}) { '' }
|
124
|
+
stylesheet.render
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'with configuration' do
|
129
|
+
it 'passes configuration to Rainpress' do
|
130
|
+
Massimo.config.css_compressor = :rainpress
|
131
|
+
Massimo.config.css_compressor_options = { :comments => false }
|
132
|
+
with_file 'stylesheets/main.css', code do
|
133
|
+
mock_module('Rainpress').compress(code, :comments => false) { '' }
|
134
|
+
stylesheet.render
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'using :yui' do
|
141
|
+
it 'compresses using YUI::CssCompressor' do
|
142
|
+
Massimo.config.css_compressor = :yui
|
143
|
+
with_file 'stylesheets/main.css', code do
|
144
|
+
compressor = mock!.compress(code) { '' }
|
145
|
+
mock_module('YUI::CssCompressor').new({}) { compressor }
|
146
|
+
stylesheet.render
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'with configuration' do
|
151
|
+
it 'passes configuration to YUI::CssCompressor' do
|
152
|
+
Massimo.config.css_compressor = :yui
|
153
|
+
Massimo.config.css_compressor_options = { :linebreak => 0 }
|
154
|
+
with_file 'stylesheets/main.css', code do
|
155
|
+
compressor = mock!.compress(code) { '' }
|
156
|
+
mock_module('YUI::CssCompressor').new(:linebreak => 0) { compressor }
|
157
|
+
stylesheet.render
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
103
163
|
end
|
data/spec/massimo/ui_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe Massimo::UI do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'does not send a Growl notification' do
|
11
|
-
dont_allow(Growl).notify
|
11
|
+
dont_allow(blank_module("Growl")).notify
|
12
12
|
Massimo::UI.say 'message'
|
13
13
|
end
|
14
14
|
|
@@ -21,13 +21,13 @@ describe Massimo::UI do
|
|
21
21
|
|
22
22
|
context 'with :growl => true' do
|
23
23
|
it 'sends a Growl Notification' do
|
24
|
-
|
24
|
+
mock_module("Growl").notify('message', anything)
|
25
25
|
Massimo::UI.say 'message', :growl => true
|
26
26
|
end
|
27
27
|
|
28
28
|
context 'and a color' do
|
29
29
|
it 'sends an uncolored Growl Notification' do
|
30
|
-
|
30
|
+
mock_module("Growl").notify('message', anything)
|
31
31
|
Massimo::UI.say 'message', :red, :growl => true
|
32
32
|
end
|
33
33
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,22 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require 'rr'
|
7
|
-
require 'construct'
|
8
|
-
require 'rack/test'
|
9
|
-
require 'unindent'
|
10
|
-
require 'sass'
|
11
|
-
require 'less'
|
12
|
-
require 'coffee-script'
|
13
|
-
require 'sprockets'
|
14
|
-
require 'jsmin'
|
15
|
-
require 'packr'
|
16
|
-
require 'yui/compressor'
|
17
|
-
require 'closure-compiler'
|
18
|
-
require 'growl'
|
19
|
-
require 'massimo'
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
Bundler.require(:default, :development)
|
4
|
+
require "rack/test"
|
5
|
+
require "construct"
|
20
6
|
|
21
7
|
# Requires supporting files with custom matchers and macros, etc,
|
22
8
|
# in ./support/ and its subdirectories.
|
@@ -29,7 +15,7 @@ RSpec.configure do |config|
|
|
29
15
|
|
30
16
|
config.before :each do
|
31
17
|
stub($stdout).puts
|
32
|
-
|
18
|
+
stub_module("Growl").notify
|
33
19
|
end
|
34
20
|
|
35
21
|
config.after :each do
|
@@ -62,4 +48,25 @@ RSpec.configure do |config|
|
|
62
48
|
result
|
63
49
|
end
|
64
50
|
alias :silence :capture
|
51
|
+
|
52
|
+
# Creates a blank module with the given name (creating base modules if necessary)
|
53
|
+
def blank_module(name)
|
54
|
+
name.split("::").inject(Object) do |memo, const|
|
55
|
+
if memo.const_defined?(const)
|
56
|
+
memo.const_get(const)
|
57
|
+
else
|
58
|
+
memo.const_set(const, Module.new)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Creates a blank module wraps it as a mock object in rr
|
64
|
+
def mock_module(name)
|
65
|
+
mock(blank_module(name))
|
66
|
+
end
|
67
|
+
|
68
|
+
# Creates a blank module wraps it as a stubbed object in rr
|
69
|
+
def stub_module(name)
|
70
|
+
stub(blank_module(name))
|
71
|
+
end
|
65
72
|
end
|