machined 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +2 -0
  3. data/LICENSE +20 -0
  4. data/README.md +49 -0
  5. data/Rakefile +6 -0
  6. data/bin/machined +4 -0
  7. data/lib/machined.rb +23 -0
  8. data/lib/machined/cli.rb +99 -0
  9. data/lib/machined/context.rb +52 -0
  10. data/lib/machined/environment.rb +297 -0
  11. data/lib/machined/helpers/asset_tag_helpers.rb +135 -0
  12. data/lib/machined/helpers/locals_helpers.rb +57 -0
  13. data/lib/machined/helpers/output_helpers.rb +43 -0
  14. data/lib/machined/helpers/render_helpers.rb +138 -0
  15. data/lib/machined/processors/front_matter_processor.rb +35 -0
  16. data/lib/machined/processors/layout_processor.rb +71 -0
  17. data/lib/machined/server.rb +37 -0
  18. data/lib/machined/sprocket.rb +55 -0
  19. data/lib/machined/static_compiler.rb +71 -0
  20. data/lib/machined/templates/site/Gemfile.tt +10 -0
  21. data/lib/machined/templates/site/assets/images/.empty_directory +0 -0
  22. data/lib/machined/templates/site/assets/javascripts/main.js.coffee +0 -0
  23. data/lib/machined/templates/site/assets/stylesheets/main.css.scss +0 -0
  24. data/lib/machined/templates/site/config.ru +2 -0
  25. data/lib/machined/templates/site/machined.rb +17 -0
  26. data/lib/machined/templates/site/pages/index.html.erb +5 -0
  27. data/lib/machined/templates/site/public/.empty_directory +0 -0
  28. data/lib/machined/templates/site/views/layouts/main.html.erb +12 -0
  29. data/lib/machined/utils.rb +31 -0
  30. data/lib/machined/version.rb +3 -0
  31. data/machined.gemspec +39 -0
  32. data/spec/machined/cli_spec.rb +154 -0
  33. data/spec/machined/context_spec.rb +20 -0
  34. data/spec/machined/environment_spec.rb +202 -0
  35. data/spec/machined/helpers/asset_tag_helpers_spec.rb +95 -0
  36. data/spec/machined/helpers/locals_helper_spec.rb +37 -0
  37. data/spec/machined/helpers/output_helpers_spec.rb +81 -0
  38. data/spec/machined/helpers/render_helpers_spec.rb +53 -0
  39. data/spec/machined/processors/front_matter_processor_spec.rb +42 -0
  40. data/spec/machined/processors/layout_processor_spec.rb +32 -0
  41. data/spec/machined/server_spec.rb +77 -0
  42. data/spec/machined/sprocket_spec.rb +36 -0
  43. data/spec/machined/static_compiler_spec.rb +85 -0
  44. data/spec/machined/utils_spec.rb +31 -0
  45. data/spec/spec_helper.rb +16 -0
  46. data/spec/support/helpers.rb +59 -0
  47. data/spec/support/match_paths_matcher.rb +20 -0
  48. metadata +389 -0
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ describe Machined::Context do
4
+ describe "#machined" do
5
+ it "returns a reference to the Machined environment" do
6
+ with_context do |context, output|
7
+ context.machined.should be(machined)
8
+ end
9
+ end
10
+ end
11
+
12
+ describe "#config" do
13
+ it "returns a reference to the Machined environment's configuration" do
14
+ with_context do |context, output|
15
+ machined.config.layout = "application"
16
+ context.config.layout.should == "application"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,202 @@
1
+ require "spec_helper"
2
+
3
+ describe Machined::Environment do
4
+ describe "#initialize" do
5
+ it "loads configuration from a config file" do
6
+ within_construct do |c|
7
+ c.file "machined.rb", <<-CONTENT.unindent
8
+ config.output_path = "site"
9
+ append_sprocket :updates
10
+ CONTENT
11
+ machined.config.output_path.should == "site"
12
+ machined.updates.should be_a(Machined::Sprocket)
13
+ end
14
+ end
15
+ end
16
+
17
+ describe "#append_sprocket" do
18
+ it "creates a new Sprockets environment" do
19
+ sprocket = machined.append_sprocket :updates
20
+ sprocket.should be_a(Sprockets::Environment)
21
+ end
22
+
23
+ it "appends the sprocket to #sprockets" do
24
+ sprocket = machined.append_sprocket :updates
25
+ machined.sprockets.last.should be(sprocket)
26
+ end
27
+
28
+ it "adds a method with the given name which returns the sprocket" do
29
+ sprocket = machined.append_sprocket :updates
30
+ machined.updates.should be(sprocket)
31
+ Machined::Environment.method_defined?(:updates).should be_false
32
+ end
33
+
34
+ it "yields the sprocket for configuration" do
35
+ yielded_sprocket = nil
36
+ sprocket = machined.append_sprocket :updates do |updates|
37
+ yielded_sprocket = updates
38
+ end
39
+ yielded_sprocket.should be(sprocket)
40
+ end
41
+
42
+ it "initializes the sprocket with a reference to the Machined environment" do
43
+ sprocket = machined.append_sprocket :updates
44
+ sprocket.machined.should be(machined)
45
+ end
46
+
47
+ it "initializes the sprocket with configuration" do
48
+ sprocket = machined.append_sprocket :updates, :root => "spec/machined"
49
+ sprocket.root.should == File.expand_path("spec/machined")
50
+ end
51
+ end
52
+
53
+ describe "#prepend_sprocket" do
54
+ it "creates a new Sprockets environment" do
55
+ sprocket = machined.prepend_sprocket :updates
56
+ sprocket.should be_a(Sprockets::Environment)
57
+ end
58
+
59
+ it "prepends the sprocket to #sprockets" do
60
+ sprocket = machined.prepend_sprocket :updates
61
+ machined.sprockets.first.should be(sprocket)
62
+ end
63
+ end
64
+
65
+ describe "#helpers" do
66
+ it "adds methods defined in the given block to the Context" do
67
+ machined.helpers do
68
+ def hello
69
+ "world"
70
+ end
71
+ end
72
+ with_context do |context, output|
73
+ context.hello.should == "world"
74
+ end
75
+ end
76
+
77
+ it "adds methods defined in the given module to the Context" do
78
+ helper = Module.new do
79
+ def hello
80
+ "world"
81
+ end
82
+ end
83
+ machined.helpers helper
84
+ with_context do |context, output|
85
+ context.hello.should == "world"
86
+ end
87
+ end
88
+ end
89
+
90
+ describe "default assets sprocket" do
91
+ it "appends the standard asset paths" do
92
+ within_construct do |c|
93
+ c.directory "assets/images"
94
+ c.directory "assets/javascripts"
95
+ c.directory "assets/stylesheets"
96
+ c.directory "vendor/assets/images"
97
+ c.directory "vendor/assets/javascripts"
98
+ c.directory "vendor/assets/stylesheets"
99
+
100
+ machined.assets.paths.should match_paths(%w(
101
+ assets/images
102
+ assets/javascripts
103
+ assets/stylesheets
104
+ vendor/assets/images
105
+ vendor/assets/javascripts
106
+ vendor/assets/stylesheets
107
+ )).with_root(c)
108
+ end
109
+ end
110
+
111
+ it "appends the available asset paths" do
112
+ within_construct do |c|
113
+ c.directory "assets/css"
114
+ c.directory "assets/img"
115
+ c.directory "assets/js"
116
+ c.directory "assets/plugins"
117
+
118
+ machined.assets.paths.should match_paths(%w(
119
+ assets/css
120
+ assets/img
121
+ assets/js
122
+ assets/plugins
123
+ )).with_root(c)
124
+ end
125
+ end
126
+
127
+ it "compiles web assets" do
128
+ within_construct do |c|
129
+ c.file "assets/javascripts/main.js", "//= require dep"
130
+ c.file "assets/javascripts/dep.js", "var app = {};"
131
+ c.file "assets/stylesheets/main.css.scss", "@import 'dep';\nbody { color: $color; }"
132
+ c.file "assets/stylesheets/_dep.scss", "$color: red;"
133
+
134
+ machined.assets["main.js"].to_s.should == "var app = {};\n"
135
+ machined.assets["main.css"].to_s.should == "body {\n color: red; }\n"
136
+ end
137
+ end
138
+ end
139
+
140
+ describe "default pages sprocket" do
141
+ it "appends the pages path" do
142
+ within_construct do |c|
143
+ c.directory "pages"
144
+ machined.pages.paths.should match_paths(%w(pages)).with_root(c)
145
+ end
146
+ end
147
+
148
+ it "compiles html pages" do
149
+ within_construct do |c|
150
+ c.file "pages/index.html.haml", "%h1 Hello World"
151
+ machined.pages["index.html"].to_s.should == "<h1>Hello World</h1>\n"
152
+ end
153
+ end
154
+ end
155
+
156
+ describe "default views sprocket" do
157
+ it "appends the views path" do
158
+ within_construct do |c|
159
+ c.directory "views"
160
+ machined.views.paths.should match_paths(%w(views)).with_root(c)
161
+ end
162
+ end
163
+
164
+ it "compiles html pages" do
165
+ within_construct do |c|
166
+ c.file "views/layouts/main.html.haml", "%h1 Hello World"
167
+ machined.views["layouts/main.html"].to_s.should == "<h1>Hello World</h1>\n"
168
+ end
169
+ end
170
+ end
171
+
172
+ describe "compression" do
173
+ context "with compress set to true" do
174
+ it "compresses javascripts and stylesheets" do
175
+ within_construct do |c|
176
+ c.file "assets/javascripts/main.js", "//= require dep"
177
+ c.file "assets/javascripts/dep.js", "var app = {};"
178
+ c.file "assets/stylesheets/main.css.scss", "@import 'dep';\nbody { color: $color; }"
179
+ c.file "assets/stylesheets/_dep.scss", "$color: red;"
180
+
181
+ Crush::Uglifier.should_receive(:compress).with("var app = {};\n").and_return("compressed")
182
+ Crush::Sass::Engine.should_receive(:compress).with("body {\n color: red; }\n").and_return("compressed")
183
+
184
+ machined :compress => true
185
+ machined.assets["main.js"].to_s.should == "compressed"
186
+ machined.assets["main.css"].to_s.should == "compressed"
187
+ end
188
+ end
189
+ end
190
+ end
191
+
192
+ context "with a js_compressor set" do
193
+ it "compresses using that compressor" do
194
+ within_construct do |c|
195
+ c.file "assets/javascripts/main.js", "var app = {};"
196
+ c.file "machined.rb", "config.js_compressor = :packr"
197
+ Crush::Packr.should_receive(:compress).with("var app = {};\n").and_return("compressed")
198
+ machined.assets["main.js"].to_s.should == "compressed"
199
+ end
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,95 @@
1
+ require "spec_helper"
2
+
3
+ describe Machined::Helpers::AssetTagHelpers do
4
+ include Machined::Helpers::AssetTagHelpers
5
+
6
+ describe "#asset_path" do
7
+ context "with URIs" do
8
+ it "returns URIs untouched" do
9
+ machined
10
+ asset_path(:js, "https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js").should ==
11
+ "https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"
12
+ asset_path(:js, "http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js").should ==
13
+ "http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"
14
+ asset_path(:js, "//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js").should ==
15
+ "//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"
16
+ end
17
+ end
18
+
19
+ context "with regular files" do
20
+ it "returns absolute paths" do
21
+ machined
22
+ asset_path(:js, "/path/to/file.js").should == "/path/to/file.js"
23
+ asset_path(:images, "/path/to/file.jpg").should == "/path/to/file.jpg"
24
+ end
25
+
26
+ it "appends the extension for javascripts and stylesheets" do
27
+ machined
28
+ asset_path(:js, "/path/to/file").should == "/path/to/file.js"
29
+ asset_path(:css, "/path/to/file").should == "/path/to/file.css"
30
+ asset_path(:images, "/path/to/file").should_not == "/path/to/file.jpg"
31
+ end
32
+
33
+ it "prepends a base URL if missing" do
34
+ machined
35
+ asset_path(:css, "main").should == "/stylesheets/main.css"
36
+ asset_path(:js, "main").should == "/javascripts/main.js"
37
+ asset_path(:images, "logo.jpg").should == "/images/logo.jpg"
38
+ end
39
+
40
+ it "appends a timestamp if the file exists in the output path" do
41
+ within_construct do |c|
42
+ file1 = c.file "public/javascripts/main.js"
43
+ file2 = c.file "public/favicon.ico"
44
+
45
+ mtime1 = Time.now - 600
46
+ file1.utime mtime1, mtime1
47
+ mtime2 = Time.now - 60
48
+ file2.utime mtime2, mtime2
49
+
50
+ machined
51
+ asset_path(:js, "main").should == "/javascripts/main.js?#{mtime1.to_i}"
52
+ asset_path(:images, "/favicon.ico").should == "/favicon.ico?#{mtime2.to_i}"
53
+ end
54
+ end
55
+ end
56
+
57
+ context "with assets" do
58
+ it "prepends a base URL if missing" do
59
+ within_construct do |c|
60
+ c.file "assets/images/logo.jpg"
61
+ c.file "assets/javascripts/main.js"
62
+ c.file "assets/stylesheets/main.css"
63
+
64
+ machined
65
+ asset_path(:css, "main").should =~ %r(^/assets/main\.css)
66
+ asset_path(:js, "main").should =~ %r(^/assets/main\.js)
67
+ asset_path(:images, "logo.jpg").should =~ %r(^/assets/logo\.jpg)
68
+ end
69
+ end
70
+
71
+ it "appends the timestamp of the asset's mtime" do
72
+ within_construct do |c|
73
+ c.file "assets/javascripts/main.js", "//= require dep"
74
+ file = c.file "assets/javascripts/dep.js"
75
+
76
+ mtime = Time.now + 600
77
+ file.utime mtime, mtime
78
+
79
+ asset_path(:js, "main").should == "/assets/main.js?#{mtime.to_i}"
80
+ end
81
+ end
82
+
83
+ it "uses the digest path if configured" do
84
+ within_construct do |c|
85
+ c.file "assets/javascrtips/main.js"
86
+
87
+ machined :digest_assets => true
88
+
89
+ asset = machined.assets["main.js"]
90
+ asset_path(:js, "main").should == "/assets/main-#{asset.digest}.js"
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,37 @@
1
+ require "spec_helper"
2
+
3
+ describe Machined::Helpers::LocalsHelpers do
4
+ describe "#locals=" do
5
+ it "sets psuedo local variables" do
6
+ with_context do |context, output|
7
+ context.locals = { :title => "Hello World", :body => nil }
8
+ context.title.should == "Hello World"
9
+ context.body.should be_nil
10
+ end
11
+ end
12
+
13
+ it "responds_to the local variable name" do
14
+ with_context do |context, output|
15
+ context.locals = { :title => "Hello World", :body => nil }
16
+ context.respond_to?(:title).should be_true
17
+ context.respond_to?(:body).should be_true
18
+ end
19
+ end
20
+
21
+ it "still raises errors if the method doesn't exist" do
22
+ with_context do |context, output|
23
+ expect { context.not_a_local }.to raise_error(NoMethodError)
24
+ context.respond_to?(:not_a_local).should be_false
25
+ end
26
+ end
27
+
28
+ it "clears local variables when set to nil" do
29
+ with_context do |context, output|
30
+ context.locals = { :title => "Hello World" }
31
+ context.locals = nil
32
+ expect { context.title }.to raise_error(NoMethodError)
33
+ context.respond_to?(:title).should be_false
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,81 @@
1
+ require "spec_helper"
2
+
3
+ describe Machined::Helpers::OutputHelpers do
4
+ describe "#current_engine" do
5
+ it "returns :haml within a Haml template" do
6
+ within_construct do |c|
7
+ c.file "pages/index.haml", "= current_engine.inspect"
8
+ machined.pages["index"].to_s.should == ":haml\n"
9
+ end
10
+ end
11
+
12
+ it "returns :erb within an ERB template" do
13
+ within_construct do |c|
14
+ c.file "pages/index.erb", "<%= current_engine.inspect %>"
15
+ machined.pages["index"].to_s.should == ":erb"
16
+ end
17
+ end
18
+
19
+ it "returns :erubis within an Erubis template" do
20
+ within_construct do |c|
21
+ c.file "pages/index.erubis", "<%= current_engine.inspect %>"
22
+ machined.pages["index"].to_s.should == ":erubis"
23
+ end
24
+ end
25
+
26
+ it "returns :slim within a Slim template" do
27
+ within_construct do |c|
28
+ c.file "pages/index.slim", "= current_engine.inspect"
29
+ machined.pages["index"].to_s.should == ":slim"
30
+ end
31
+ end
32
+ end
33
+
34
+ describe "#capture and #concat" do
35
+ it "captures blocks in haml" do
36
+ within_construct do |c|
37
+ c.file "pages/index.haml", <<-CONTENT.unindent
38
+ - content_tag :h1 do
39
+ Hello World
40
+ CONTENT
41
+
42
+ machined.pages["index"].to_s.strip.should == "<h1>Hello World\n</h1>"
43
+ end
44
+ end
45
+
46
+ it "captures blocks in erb" do
47
+ within_construct do |c|
48
+ c.file "pages/index.erb", <<-CONTENT.unindent
49
+ <% content_tag :h1 do %>
50
+ Hello World
51
+ <% end %>
52
+ CONTENT
53
+
54
+ machined.pages["index"].to_s.strip.should == "<h1> Hello World\n</h1>"
55
+ end
56
+ end
57
+
58
+ it "captures blocks in erubis" do
59
+ within_construct do |c|
60
+ c.file "pages/index.erubis", <<-CONTENT.unindent
61
+ <% content_tag :h1 do %>
62
+ Hello World
63
+ <% end %>
64
+ CONTENT
65
+
66
+ machined.pages["index"].to_s.strip.should == "<h1> Hello World\n</h1>"
67
+ end
68
+ end
69
+
70
+ it "captures blocks in slim" do
71
+ within_construct do |c|
72
+ c.file "pages/index.slim", <<-CONTENT.unindent
73
+ - content_tag :h1 do
74
+ | Hello World
75
+ CONTENT
76
+
77
+ machined.pages["index"].to_s.strip.should == "<h1>Hello World</h1>"
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,53 @@
1
+ require "spec_helper"
2
+
3
+ describe Machined::Helpers::RenderHelpers do
4
+ describe "#render" do
5
+ it "renders partials" do
6
+ within_construct do |c|
7
+ c.file "pages/index.html.erb", <<-CONTENT.unindent
8
+ <%= render "partial1" %>
9
+ <%= render "partial2" %>
10
+ <%= render "partials/partial3" %>
11
+ CONTENT
12
+ c.file "views/partial1.md", "# Hello World"
13
+ c.file "views/_partial2.haml", "%p Here's some Content..."
14
+ c.file "views/partials/_partial3.html", "<p>And some more</p>\n"
15
+
16
+ # puts machined.views.paths.inspect
17
+ machined.pages["index.html"].to_s.should == <<-CONTENT.unindent
18
+ <h1>Hello World</h1>
19
+ <p>Here's some Content...</p>
20
+ <p>And some more</p>
21
+ CONTENT
22
+ end
23
+ end
24
+
25
+ it "renders partials with locals" do
26
+ within_construct do |c|
27
+ c.file "pages/index.html.erb", %(<%= render "partial", :text => "Hello World" %>)
28
+ c.file "views/partial.haml", "%h1= text"
29
+
30
+ machined.pages["index.html"].to_s.should == "<h1>Hello World</h1>\n"
31
+ end
32
+ end
33
+
34
+ it "renders partial collections" do
35
+ within_construct do |c|
36
+ c.file "pages/index.html.erb", %(<%= render "number", :collection => [1,2,3] %>)
37
+ c.file "views/number.haml", "= number\n= number_counter"
38
+
39
+ machined.pages["index.html"].to_s.should == "1\n1\n2\n2\n3\n3\n"
40
+ end
41
+ end
42
+
43
+ it "raises a Sprockets::FileNotFound error if the partial is missing" do
44
+ within_construct do |c|
45
+ c.file "pages/index.html.erb", %(<%= render "partial" %>)
46
+
47
+ expect {
48
+ machined.pages["index.html"].to_s
49
+ }.to raise_error(Sprockets::FileNotFound)
50
+ end
51
+ end
52
+ end
53
+ end