smartgen 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/ChangeLog.md +14 -0
  2. data/Gemfile.lock +2 -2
  3. data/README.md +7 -0
  4. data/lib/smartgen/configuration.rb +1 -49
  5. data/lib/smartgen/engines.rb +1 -0
  6. data/lib/smartgen/engines/base.rb +3 -3
  7. data/lib/smartgen/engines/erb.rb +15 -0
  8. data/lib/smartgen/engines/markdown.rb +1 -1
  9. data/lib/smartgen/engines/textile.rb +1 -1
  10. data/lib/smartgen/generator.rb +29 -17
  11. data/lib/smartgen/markup_file.rb +6 -2
  12. data/lib/smartgen/object_hash.rb +15 -5
  13. data/lib/smartgen/rake_task.rb +21 -5
  14. data/lib/smartgen/renderers/erb.rb +1 -4
  15. data/lib/smartgen/resource.rb +1 -9
  16. data/lib/smartgen/version.rb +1 -1
  17. data/spec/fixtures/expectations/common/another_index.html +13 -0
  18. data/spec/fixtures/expectations/common/index.html +8 -0
  19. data/spec/fixtures/expectations/common/other_index.html +13 -0
  20. data/spec/fixtures/expectations/erb/index.html +15 -0
  21. data/spec/fixtures/expectations/erb/with_layout/index.html +19 -0
  22. data/spec/fixtures/expectations/indexer/index_with_indexer.html +16 -0
  23. data/spec/fixtures/expectations/indexer/index_with_indexer_and_numbered_index.html +16 -0
  24. data/spec/fixtures/expectations/with_layout/index.html +12 -0
  25. data/spec/fixtures/expectations/with_layout/index_with_metadata.html +43 -0
  26. data/spec/fixtures/expectations/with_layout/index_with_specific_metadata.html +44 -0
  27. data/spec/fixtures/src/assets/images/image.gif +0 -0
  28. data/spec/fixtures/src/assets/javascripts/somelib.js +2 -0
  29. data/spec/fixtures/src/assets/stylesheets/style.css +2 -0
  30. data/spec/fixtures/src/common/another_index.md +12 -0
  31. data/spec/fixtures/src/common/index.textile +10 -0
  32. data/spec/fixtures/src/common/other_index.markdown +12 -0
  33. data/spec/fixtures/src/common/somefile +10 -0
  34. data/spec/fixtures/src/erb/index.html.erb +7 -0
  35. data/spec/fixtures/src/erb/with_layout/index.html.erb +7 -0
  36. data/spec/fixtures/src/erb/with_layout/layout.html.erb +5 -0
  37. data/spec/fixtures/src/indexer/index_with_indexer.textile +26 -0
  38. data/spec/fixtures/src/indexer/index_with_indexer_and_numbered_index.textile +26 -0
  39. data/spec/fixtures/src/layout.html.erb +5 -0
  40. data/spec/fixtures/src/layout_with_metadata.html.erb +22 -0
  41. data/spec/fixtures/src/layout_with_specific_metadata.html.erb +23 -0
  42. data/spec/fixtures/src/metadata.yml +43 -0
  43. data/spec/fixtures/src/with_layout/index.textile +10 -0
  44. data/spec/fixtures/src/with_layout/index_with_specific_metadata.textile +10 -0
  45. data/spec/lib/smartgen/configuration_spec.rb +5 -0
  46. data/spec/lib/smartgen/engines/base_spec.rb +73 -0
  47. data/spec/lib/smartgen/engines/erb_spec.rb +37 -0
  48. data/spec/lib/smartgen/engines/markdown_spec.rb +23 -0
  49. data/spec/lib/smartgen/engines/textile_spec.rb +19 -0
  50. data/spec/lib/smartgen/generator_spec.rb +272 -0
  51. data/spec/lib/smartgen/indexer_spec.rb +122 -0
  52. data/spec/lib/smartgen/markup_file_spec.rb +168 -0
  53. data/spec/lib/smartgen/object_hash_spec.rb +91 -0
  54. data/spec/lib/smartgen/renderers/erb_spec.rb +32 -0
  55. data/spec/lib/smartgen/resource_spec.rb +73 -0
  56. data/spec/lib/smartgen/watcher_spec.rb +71 -0
  57. data/spec/lib/smartgen_spec.rb +18 -0
  58. data/spec/sandbox/.gitkeep +0 -0
  59. data/spec/spec_helper.rb +37 -0
  60. metadata +99 -13
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Smartgen::Configuration do
4
+ it { subject.should be_kind_of(Smartgen::ObjectHash) }
5
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe Smartgen::Engine::Base do
4
+ describe "processing" do
5
+ describe "pre processing" do
6
+ before do
7
+ Smartgen::Engine::Base.pre_processors = []
8
+ end
9
+
10
+ context "without pre processors" do
11
+ it "should just return body" do
12
+ body = 'body'
13
+ subject.process(body).should == body
14
+ end
15
+ end
16
+
17
+ context "with pre processors" do
18
+ class PreProcessor
19
+ def process(body, metadata=Smartgen::ObjectHash.new) # just needs to respond_to?(:process)
20
+ "<pre_processed>#{body}#{metadata[:name]}</pre_processed>"
21
+ end
22
+ end
23
+
24
+ it "should pre process body" do
25
+ Smartgen::Engine::Base.register(PreProcessor.new)
26
+
27
+ body = 'body'
28
+ subject.process(body).should == "<pre_processed>#{body}</pre_processed>"
29
+ end
30
+
31
+ it "should pre process body with metadata" do
32
+ Smartgen::Engine::Base.register(PreProcessor.new)
33
+
34
+ body = 'body'
35
+ subject.process(body, Smartgen::ObjectHash.new({:name => " John"})).should == "<pre_processed>body John</pre_processed>"
36
+ end
37
+
38
+ it "should do run pre processors in the order they were registered" do
39
+ class AnotherPreProcessor
40
+ def process(body, metadata={})
41
+ body.gsub(/pre_processed/, 'another')
42
+ end
43
+ end
44
+
45
+ Smartgen::Engine::Base.register(PreProcessor.new)
46
+ Smartgen::Engine::Base.register(AnotherPreProcessor.new)
47
+
48
+ body = 'body'
49
+ subject.process(body).should == "<another>#{body}</another>"
50
+ end
51
+
52
+ context "of a subclass" do
53
+ class OtherPreProcessor
54
+ def process(body, metadata={})
55
+ "<another>#{body}</another>"
56
+ end
57
+ end
58
+
59
+ class MyCustomEngine < Smartgen::Engine::Base
60
+ end
61
+
62
+ it "should pre process body with different processor of ancestor" do
63
+ Smartgen::Engine::Base.register(PreProcessor.new)
64
+ MyCustomEngine.register(OtherPreProcessor.new)
65
+
66
+ body = 'body'
67
+ MyCustomEngine.new.process(body).should == "<another>#{body}</another>"
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Smartgen::Engine::ERB do
4
+ let :body do
5
+ "2 + 2 = <%= 2 * 2 %>"
6
+ end
7
+
8
+ let :contents do
9
+ "2 + 2 = 4"
10
+ end
11
+
12
+ it "should process body using ERB" do
13
+ subject.process(body).should == contents
14
+ end
15
+
16
+ it "should support .erb extension" do
17
+ should be_supported('.erb')
18
+ end
19
+
20
+ context "with metadata" do
21
+ let :body do
22
+ "Some metadata: <%= metadata.name %>"
23
+ end
24
+
25
+ let :contents do
26
+ "Some metadata: #{metadata.name}"
27
+ end
28
+
29
+ let :metadata do
30
+ Smartgen::ObjectHash.new :name => 'Vicente'
31
+ end
32
+
33
+ it "should process body using ERB" do
34
+ subject.process(body, metadata).should == contents
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Smartgen::Engine::Markdown do
4
+ def body
5
+ "# Some Header\n\nSome paragraph"
6
+ end
7
+
8
+ def contents
9
+ "<h1>Some Header</h1>\n\n<p>Some paragraph</p>"
10
+ end
11
+
12
+ it "should process body using BlueCloth" do
13
+ subject.process(body).should == contents
14
+ end
15
+
16
+ it "should support .md extension" do
17
+ should be_supported('.md')
18
+ end
19
+
20
+ it "should support .markdown extension" do
21
+ should be_supported('.markdown')
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Smartgen::Engine::Textile do
4
+ def body
5
+ "h1. Some Header\n\nSome paragraph"
6
+ end
7
+
8
+ def contents
9
+ "<h1>Some Header</h1>\n<p>Some paragraph</p>"
10
+ end
11
+
12
+ it "should process body using RedCloth" do
13
+ subject.process(body).should == contents
14
+ end
15
+
16
+ it "should support .textile extension" do
17
+ should be_supported('.textile')
18
+ end
19
+ end
@@ -0,0 +1,272 @@
1
+ require 'spec_helper'
2
+ require 'fileutils'
3
+
4
+ describe Smartgen::Generator do
5
+ def src_files
6
+ [fixture('src/common/**/*')]
7
+ end
8
+
9
+ def output_folder
10
+ sandbox('doc')
11
+ end
12
+
13
+ def output_folder_file(path)
14
+ File.join(output_folder, path)
15
+ end
16
+
17
+ def actual_src_files
18
+ Dir[*src_files].select { |f| ['.textile', '.markdown', '.md'].include?(File.extname(f)) }
19
+ end
20
+
21
+ def actual_src_filenames
22
+ actual_src_files.map { |f| [File.basename(f, File.extname(f)), File.extname(f)] }
23
+ end
24
+
25
+ def read_output(filename)
26
+ File.read(output_folder_file(filename))
27
+ end
28
+
29
+ def read_fixture(filename)
30
+ File.read(fixture(filename))
31
+ end
32
+
33
+ def arguments
34
+ [src_files, output_folder]
35
+ end
36
+
37
+ def options
38
+ {}
39
+ end
40
+
41
+ subject { Smartgen::Generator.new arguments, options, { :verbose => false } }
42
+
43
+ before do
44
+ FileUtils.rm_rf output_folder
45
+ end
46
+
47
+ describe "generation" do
48
+ it "should create the output folder" do
49
+ capture(:stdout) { subject.invoke_all }
50
+ File.should be_directory(output_folder)
51
+ end
52
+
53
+ it "should create HTML files for each markup template in src_files" do
54
+ capture(:stdout) { subject.invoke_all }
55
+
56
+ actual_src_filenames.each do |src_filename, src_ext|
57
+ File.should be_file(output_folder_file("#{src_filename}.html"))
58
+ end
59
+ end
60
+
61
+ it "should convert markup files into HTML files when generating" do
62
+ capture(:stdout) { subject.invoke_all }
63
+ actual_src_filenames.each do |src_filename, src_ext|
64
+ read_output("#{src_filename}.html").should == read_fixture("expectations/common/#{src_filename}.html")
65
+ end
66
+ end
67
+
68
+ it "should always force generation of each file, even if it exists" do
69
+ FileUtils.mkdir_p(output_folder)
70
+ File.open(output_folder_file("index.html"), 'w') { |f| f.write('old contents') }
71
+ capture(:stdout) { subject.invoke_all }
72
+ read_output("index.html").should == read_fixture("expectations/common/index.html")
73
+ end
74
+
75
+ context "with nil layout" do
76
+ def options
77
+ { :layout => nil }
78
+ end
79
+
80
+ it "should not use layout" do
81
+ capture(:stdout) { subject.invoke_all }
82
+ actual_src_filenames.each do |src_filename, src_ext|
83
+ read_output("#{src_filename}.html").should == read_fixture("expectations/common/#{src_filename}.html")
84
+ end
85
+ end
86
+ end
87
+
88
+ describe "inexistent file" do
89
+ def src_files
90
+ [fixture('src/common/inexistent_file.textile')]
91
+ end
92
+
93
+ it "should not generate html" do
94
+ capture(:stdout) { subject.invoke_all }
95
+ File.should_not be_file(output_folder_file("inexistent_file.html"))
96
+ end
97
+ end
98
+
99
+ describe "with ERB files" do
100
+ def src_files
101
+ [fixture('src/erb/index.html.erb')]
102
+ end
103
+
104
+ it "should generate index file" do
105
+ capture(:stdout) { subject.invoke_all }
106
+ read_output("index.html").should == read_fixture("expectations/erb/index.html")
107
+ end
108
+
109
+ describe "with layout" do
110
+ def src_files
111
+ [fixture('src/erb/with_layout/index.html.erb')]
112
+ end
113
+
114
+ def options
115
+ { :layout => fixture('src/layout.html.erb') }
116
+ end
117
+
118
+ it "should use the layout when generating" do
119
+ capture(:stdout) { subject.invoke_all }
120
+ read_output("index.html").should == read_fixture("expectations/erb/with_layout/index.html")
121
+ end
122
+
123
+ context "inside the src_files pattern" do
124
+ def src_files
125
+ [fixture('src/erb/with_layout/**/*')]
126
+ end
127
+
128
+ def options
129
+ { :layout => fixture('src/erb/with_layout/layout.html.erb') }
130
+ end
131
+
132
+ it "should use the layout when generating" do
133
+ capture(:stdout) { subject.invoke_all }
134
+ read_output("index.html").should == read_fixture("expectations/erb/with_layout/index.html")
135
+ end
136
+
137
+ it "should not attempt to render layout using ERB engine" do
138
+ capture(:stdout) { subject.invoke_all }
139
+ read_output("index.html").should == read_fixture("expectations/erb/with_layout/index.html")
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ describe "with layout" do
146
+ def src_files
147
+ [fixture('src/with_layout/index.textile')]
148
+ end
149
+
150
+ def options
151
+ { :layout => fixture('src/layout.html.erb') }
152
+ end
153
+
154
+ it "should use the layout when generating" do
155
+ capture(:stdout) { subject.invoke_all }
156
+ read_output("index.html").should == read_fixture("expectations/with_layout/index.html")
157
+ end
158
+
159
+ describe "and metadata" do
160
+ def options
161
+ { :layout => fixture('src/layout_with_metadata.html.erb'), :metadata_file => fixture('src/metadata.yml') }
162
+ end
163
+
164
+ it "should load metadata from file and expose it when rendering files" do
165
+ capture(:stdout) { subject.invoke_all }
166
+ read_output("index.html").should == read_fixture("expectations/with_layout/index_with_metadata.html")
167
+ end
168
+
169
+ describe "using conventions" do
170
+ def src_files
171
+ [fixture('src/with_layout/index_with_specific_metadata.textile')]
172
+ end
173
+
174
+ def options
175
+ { :layout => fixture('src/layout_with_specific_metadata.html.erb'), :metadata_file => fixture('src/metadata.yml') }
176
+ end
177
+
178
+ it "should expose metadata for current page data for each file in metadata.current_page" do
179
+ capture(:stdout) { subject.invoke_all }
180
+ read_output("index_with_specific_metadata.html").should == read_fixture("expectations/with_layout/index_with_specific_metadata.html")
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+ describe "assets" do
187
+ def assets
188
+ [fixture("src/assets/images"), fixture("src/assets/javascripts"), fixture("src/assets/stylesheets")]
189
+ end
190
+
191
+ def options
192
+ { :assets => assets }
193
+ end
194
+
195
+ it "should copy directories to output folder" do
196
+ capture(:stdout) { subject.invoke_all }
197
+
198
+ File.should be_directory(output_folder_file('images'))
199
+ File.should be_directory(output_folder_file('javascripts'))
200
+ end
201
+
202
+ it "should copy the contents of the given directories to output folder" do
203
+ capture(:stdout) { subject.invoke_all }
204
+
205
+ File.should be_file(output_folder_file('images/image.gif'))
206
+ File.should be_file(output_folder_file('javascripts/somelib.js'))
207
+ File.should be_file(output_folder_file('stylesheets/style.css'))
208
+ end
209
+
210
+ it "should force copy of the contents of the given directories to output folder" do
211
+ FileUtils.mkdir_p(output_folder_file('javascripts'))
212
+ File.open(output_folder_file('javascripts/somelib.js'), 'w') { |f| f.write('//some code') }
213
+
214
+ capture(:stdout) { subject.invoke_all }
215
+ read_output('javascripts/somelib.js').should == read_fixture('src/assets/javascripts/somelib.js')
216
+ end
217
+ end
218
+
219
+ describe "with indexer" do
220
+ def src_files
221
+ [fixture('src/indexer/index_with_indexer.textile')]
222
+ end
223
+
224
+ def options
225
+ { :use_indexer => true }
226
+ end
227
+
228
+ it "should add IDs to each <h> tag" do
229
+ capture(:stdout) { subject.invoke_all }
230
+
231
+ actual_src_filenames.each do |src_filename, src_ext|
232
+ read_output("#{src_filename}.html").should == read_fixture("expectations/indexer/#{src_filename}.html")
233
+ end
234
+ end
235
+
236
+ context "and numbered_index" do
237
+ def src_files
238
+ [fixture('src/indexer/index_with_indexer_and_numbered_index.textile')]
239
+ end
240
+
241
+ def options
242
+ { :use_indexer => true, :numbered_index => true }
243
+ end
244
+
245
+ it "should add numbered indexes on each <h> tag" do
246
+ capture(:stdout) { subject.invoke_all }
247
+
248
+ actual_src_filenames.each do |src_filename, src_ext|
249
+ read_output("#{src_filename}.html").should == read_fixture("expectations/indexer/#{src_filename}.html")
250
+ end
251
+ end
252
+ end
253
+ end
254
+ end
255
+
256
+ describe "renderer registration" do
257
+ it "should register ERB renderer by default" do
258
+ Smartgen::Generator.renderer.should be_an_instance_of(Smartgen::Renderer::ERB)
259
+ end
260
+
261
+ it "should allow the registration of a custom renderer" do
262
+ class MyRenderer
263
+ def render(layout, markup_file)
264
+ "do some rendering stuff"
265
+ end
266
+ end
267
+
268
+ Smartgen::Generator.renderer = MyRenderer.new
269
+ Smartgen::Generator.renderer.render('some_layout', mock(Smartgen::MarkupFile)).should == "do some rendering stuff"
270
+ end
271
+ end
272
+ end
@@ -0,0 +1,122 @@
1
+ require 'spec_helper'
2
+
3
+ describe Smartgen::Indexer do
4
+ matcher :have_tag do |tag, attributes|
5
+ match do |actual|
6
+ tags = Nokogiri::HTML(actual).css(tag.to_s)
7
+ tags.present? && tags.any? do |tag|
8
+ attributes.all? do |attribute, value|
9
+ tag.has_attribute?(attribute.to_s) && tag[attribute.to_s] == value
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ matcher :have_tag_with_contents do |tag, content|
16
+ match do |actual|
17
+ tags = Nokogiri::HTML(actual).css(tag.to_s)
18
+ tags.present? && tags.any? do |tag|
19
+ tag.content == content
20
+ end
21
+ end
22
+ end
23
+
24
+ def html
25
+ "<h1>Some header</h1>"
26
+ end
27
+
28
+ subject { Smartgen::Indexer.new html }
29
+
30
+ describe "addition of IDs" do
31
+ def html
32
+ return <<-HTML
33
+ <html>
34
+ <body>
35
+ <h1>A h1 header</h1>
36
+ <h2>A h2 header</h2>
37
+ <h3>A h3 header</h3>
38
+ <h4>A h4 header</h4>
39
+ <h5>A h5 header</h5>
40
+ <h6>A h6 header</h6>
41
+ </body>
42
+ </html>
43
+ HTML
44
+ end
45
+
46
+ 1.upto(6).each do |header_level|
47
+ it "should add IDs for each <h#{header_level}> tag in the result" do
48
+ subject.result.should have_tag("h#{header_level}", :id => "a-h#{header_level}-header")
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "index" do
54
+ def html
55
+ return <<-HTML
56
+ <html>
57
+ <body>
58
+ <h1>A h1 header</h1>
59
+ <h2>A h2 header</h2>
60
+ <h3>A h3 header</h3>
61
+ <h3>Some other h3 header</h3>
62
+ <h2>Another h2 header</h2>
63
+ <h5>A h5 header</h5>
64
+ <h2>Yet Another h2 header</h2>
65
+ <h3>Yet Another h3 header</h3>
66
+ <h1>Other h1 header</h1>
67
+ </body>
68
+ </html>
69
+ HTML
70
+ end
71
+
72
+ it "should return an index with headers data hierarquically distributed" do
73
+ expected_index = [
74
+ { :text => 'A h1 header', :id => 'a-h1-header', :level => 1, :children => [
75
+ { :text => 'A h2 header', :id => 'a-h2-header', :level => 2, :children => [
76
+ { :text => 'A h3 header', :id => 'a-h3-header', :level => 3, :children => [] },
77
+ { :text => 'Some other h3 header', :id => 'some-other-h3-header', :level => 3, :children => [] }
78
+ ] },
79
+ { :text => 'Another h2 header', :id => 'another-h2-header', :level => 2, :children => [
80
+ { :text => 'A h5 header', :id => 'a-h5-header', :level => 5, :children => [] }
81
+ ] },
82
+ { :text => 'Yet Another h2 header', :id => 'yet-another-h2-header', :level => 2, :children => [
83
+ { :text => 'Yet Another h3 header', :id => 'yet-another-h3-header', :level => 3, :children => [] }
84
+ ] },
85
+ ]},
86
+ { :text => 'Other h1 header', :id => 'other-h1-header', :level => 1, :children => [] }
87
+ ]
88
+
89
+ subject.index.should == expected_index
90
+ end
91
+
92
+ context "when numbered_index options is given" do
93
+ subject { Smartgen::Indexer.new html, :numbered_index => true }
94
+
95
+ it "should add the numbered index to header contents" do
96
+ subject.result.should have_tag_with_contents("h1", "1 A h1 header")
97
+ subject.result.should have_tag_with_contents("h2", "1.1 A h2 header")
98
+ subject.result.should have_tag_with_contents("h3", "1.1.2 Some other h3 header")
99
+ end
100
+
101
+ it "should return an index with headers data hierarquically distributed with numbered index" do
102
+ expected_index = [
103
+ { :text => 'A h1 header', :id => 'a-h1-header', :level => 1, :numbered_index => '1', :children => [
104
+ { :text => 'A h2 header', :id => 'a-h2-header', :level => 2, :numbered_index => '1.1', :children => [
105
+ { :text => 'A h3 header', :id => 'a-h3-header', :level => 3, :numbered_index => '1.1.1', :children => [] },
106
+ { :text => 'Some other h3 header', :id => 'some-other-h3-header', :level => 3, :numbered_index => '1.1.2', :children => [] }
107
+ ] },
108
+ { :text => 'Another h2 header', :id => 'another-h2-header', :level => 2, :numbered_index => '1.2', :children => [
109
+ { :text => 'A h5 header', :id => 'a-h5-header', :level => 5, :numbered_index => '1.2.1', :children => [] }
110
+ ] },
111
+ { :text => 'Yet Another h2 header', :id => 'yet-another-h2-header', :level => 2, :numbered_index => '1.3', :children => [
112
+ { :text => 'Yet Another h3 header', :id => 'yet-another-h3-header', :level => 3, :numbered_index => '1.3.1', :children => [] }
113
+ ] },
114
+ ]},
115
+ { :text => 'Other h1 header', :id => 'other-h1-header', :level => 1, :numbered_index => '2', :children => [] }
116
+ ]
117
+
118
+ subject.index.should == expected_index
119
+ end
120
+ end
121
+ end
122
+ end