smartgen 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/ChangeLog.md +4 -0
  2. data/Gemfile +11 -0
  3. data/Gemfile.lock +61 -0
  4. data/README.md +119 -0
  5. data/Rakefile +8 -0
  6. data/bin/smartgen +25 -0
  7. data/lib/smartgen.rb +21 -0
  8. data/lib/smartgen/configuration.rb +17 -0
  9. data/lib/smartgen/engines.rb +3 -0
  10. data/lib/smartgen/engines/base.rb +45 -0
  11. data/lib/smartgen/engines/markdown.rb +16 -0
  12. data/lib/smartgen/engines/textile.rb +16 -0
  13. data/lib/smartgen/generator.rb +104 -0
  14. data/lib/smartgen/markup_file.rb +47 -0
  15. data/lib/smartgen/object_hash.rb +41 -0
  16. data/lib/smartgen/renderers.rb +1 -0
  17. data/lib/smartgen/renderers/erb.rb +12 -0
  18. data/lib/smartgen/resource.rb +32 -0
  19. data/lib/smartgen/version.rb +4 -0
  20. data/spec/fixtures/expectations/common/another_index.html +13 -0
  21. data/spec/fixtures/expectations/common/index.html +8 -0
  22. data/spec/fixtures/expectations/common/other_index.html +13 -0
  23. data/spec/fixtures/expectations/with_layout/index.html +12 -0
  24. data/spec/fixtures/expectations/with_layout/index_with_metadata.html +43 -0
  25. data/spec/fixtures/expectations/with_layout/index_with_specific_metadata.html +44 -0
  26. data/spec/fixtures/src/assets/images/image.gif +0 -0
  27. data/spec/fixtures/src/assets/javascripts/somelib.js +2 -0
  28. data/spec/fixtures/src/assets/stylesheets/style.css +2 -0
  29. data/spec/fixtures/src/common/another_index.md +12 -0
  30. data/spec/fixtures/src/common/index.textile +10 -0
  31. data/spec/fixtures/src/common/other_index.markdown +12 -0
  32. data/spec/fixtures/src/layout.html.erb +5 -0
  33. data/spec/fixtures/src/layout_with_metadata.html.erb +22 -0
  34. data/spec/fixtures/src/layout_with_specific_metadata.html.erb +23 -0
  35. data/spec/fixtures/src/metadata.yml +43 -0
  36. data/spec/fixtures/src/with_layout/index.textile +10 -0
  37. data/spec/fixtures/src/with_layout/index_with_specific_metadata.textile +10 -0
  38. data/spec/lib/smartgen/configuration_spec.rb +30 -0
  39. data/spec/lib/smartgen/engines/base_spec.rb +71 -0
  40. data/spec/lib/smartgen/engines/markdown_spec.rb +23 -0
  41. data/spec/lib/smartgen/engines/textile_spec.rb +19 -0
  42. data/spec/lib/smartgen/generator_spec.rb +166 -0
  43. data/spec/lib/smartgen/markup_file_spec.rb +128 -0
  44. data/spec/lib/smartgen/object_hash_spec.rb +54 -0
  45. data/spec/lib/smartgen/renderers/erb_spec.rb +32 -0
  46. data/spec/lib/smartgen/resource_spec.rb +60 -0
  47. data/spec/lib/smartgen_spec.rb +18 -0
  48. data/spec/sandbox/.gitkeep +0 -0
  49. data/spec/spec_helper.rb +37 -0
  50. metadata +240 -0
@@ -0,0 +1,10 @@
1
+ h1. Here is some header
2
+
3
+ And here is a paragraph
4
+
5
+ * some bullet lists with *style*
6
+ * some bullet lists with _style_
7
+
8
+ h2. Another header
9
+
10
+ With some text
@@ -0,0 +1,10 @@
1
+ h1. Here is some header
2
+
3
+ And here is a paragraph
4
+
5
+ * some bullet lists with *style*
6
+ * some bullet lists with _style_
7
+
8
+ h2. Another header
9
+
10
+ With some text
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe Smartgen::Configuration do
4
+ matcher :be_an_empty_array do
5
+ match { |actual| actual.instance_of?(Array) && actual.empty? }
6
+ end
7
+
8
+ describe "defaults" do
9
+ it "should initialize src_files to an empty array" do
10
+ subject.src_files.should be_an_empty_array
11
+ subject.src_files.should be_empty
12
+ end
13
+
14
+ it "should initialize output folder to 'tmp'" do
15
+ subject.output_folder.should == 'tmp'
16
+ end
17
+
18
+ it "should initialize layout to nil" do
19
+ subject.layout.should be_nil
20
+ end
21
+
22
+ it "should initialize assets to an empty array" do
23
+ subject.assets.should be_an_empty_array
24
+ end
25
+
26
+ it "should initialize metadata_file to 'metadata.yml'" do
27
+ subject.metadata_file.should == 'metadata.yml'
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe Smartgen::Engine::Base do
4
+ describe "processing" do
5
+ it "should just return body" do
6
+ body = 'body'
7
+ subject.process(body).should == body
8
+ end
9
+
10
+ describe "pre processing" do
11
+ before do
12
+ Smartgen::Engine::Base.pre_processors = []
13
+ end
14
+
15
+ context "without pre processors" do
16
+ it "should just return body" do
17
+ body = 'body'
18
+ subject.process(body).should == body
19
+ end
20
+ end
21
+
22
+ context "with pre processors" do
23
+ class PreProcessor
24
+ def process(body) # just needs to respond_to?(:process)
25
+ "<pre_processed>#{body}</pre_processed>"
26
+ end
27
+ end
28
+
29
+ it "should pre process body" do
30
+ Smartgen::Engine::Base.register(PreProcessor.new)
31
+
32
+ body = 'body'
33
+ subject.process(body).should == "<pre_processed>#{body}</pre_processed>"
34
+ end
35
+
36
+ it "should do run pre processors in the order they were registered" do
37
+ class AnotherPreProcessor
38
+ def process(body)
39
+ body.gsub(/pre_processed/, 'another')
40
+ end
41
+ end
42
+
43
+ Smartgen::Engine::Base.register(PreProcessor.new)
44
+ Smartgen::Engine::Base.register(AnotherPreProcessor.new)
45
+
46
+ body = 'body'
47
+ subject.process(body).should == "<another>#{body}</another>"
48
+ end
49
+
50
+ context "of a subclass" do
51
+ class OtherPreProcessor
52
+ def process(body)
53
+ "<another>#{body}</another>"
54
+ end
55
+ end
56
+
57
+ class MyCustomEngine < Smartgen::Engine::Base
58
+ end
59
+
60
+ it "should pre process body with different processor of ancestor" do
61
+ Smartgen::Engine::Base.register(PreProcessor.new)
62
+ MyCustomEngine.register(OtherPreProcessor.new)
63
+
64
+ body = 'body'
65
+ MyCustomEngine.new.process(body).should == "<another>#{body}</another>"
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ 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,166 @@
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
+ describe "with layout" do
76
+ def src_files
77
+ [fixture('src/with_layout/index.textile')]
78
+ end
79
+
80
+ def options
81
+ { :layout => fixture('src/layout.html.erb') }
82
+ end
83
+
84
+ it "should use the layout when generating" do
85
+ capture(:stdout) { subject.invoke_all }
86
+ read_output("index.html").should == read_fixture("expectations/with_layout/index.html")
87
+ end
88
+
89
+ describe "and metadata" do
90
+ def options
91
+ { :layout => fixture('src/layout_with_metadata.html.erb'), :metadata_file => fixture('src/metadata.yml') }
92
+ end
93
+
94
+ it "should load metadata from file and expose it when rendering files" do
95
+ capture(:stdout) { subject.invoke_all }
96
+ read_output("index.html").should == read_fixture("expectations/with_layout/index_with_metadata.html")
97
+ end
98
+
99
+ describe "using conventions" do
100
+ def src_files
101
+ [fixture('src/with_layout/index_with_specific_metadata.textile')]
102
+ end
103
+
104
+ def options
105
+ { :layout => fixture('src/layout_with_specific_metadata.html.erb'), :metadata_file => fixture('src/metadata.yml') }
106
+ end
107
+
108
+ it "should expose metadata for current page data for each file in metadata.current_page" do
109
+ capture(:stdout) { subject.invoke_all }
110
+ read_output("index_with_specific_metadata.html").should == read_fixture("expectations/with_layout/index_with_specific_metadata.html")
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ describe "assets" do
117
+ def assets
118
+ [fixture("src/assets/images"), fixture("src/assets/javascripts"), fixture("src/assets/stylesheets")]
119
+ end
120
+
121
+ def options
122
+ { :assets => assets }
123
+ end
124
+
125
+ it "should copy directories to output folder" do
126
+ capture(:stdout) { subject.invoke_all }
127
+
128
+ File.should be_directory(output_folder_file('images'))
129
+ File.should be_directory(output_folder_file('javascripts'))
130
+ end
131
+
132
+ it "should copy the contents of the given directories to output folder" do
133
+ capture(:stdout) { subject.invoke_all }
134
+
135
+ File.should be_file(output_folder_file('images/image.gif'))
136
+ File.should be_file(output_folder_file('javascripts/somelib.js'))
137
+ File.should be_file(output_folder_file('stylesheets/style.css'))
138
+ end
139
+
140
+ it "should force copy of the contents of the given directories to output folder" do
141
+ FileUtils.mkdir_p(output_folder_file('javascripts'))
142
+ File.open(output_folder_file('javascripts/somelib.js'), 'w') { |f| f.write('//some code') }
143
+
144
+ capture(:stdout) { subject.invoke_all }
145
+ read_output('javascripts/somelib.js').should == read_fixture('src/assets/javascripts/somelib.js')
146
+ end
147
+ end
148
+ end
149
+
150
+ describe "renderer registration" do
151
+ it "should register ERB renderer by default" do
152
+ Smartgen::Generator.renderer.should be_an_instance_of(Smartgen::Renderer::ERB)
153
+ end
154
+
155
+ it "should allow the registration of a custom renderer" do
156
+ class MyRenderer
157
+ def render(layout, markup_file)
158
+ "do some rendering stuff"
159
+ end
160
+ end
161
+
162
+ Smartgen::Generator.renderer = MyRenderer.new
163
+ Smartgen::Generator.renderer.render('some_layout', mock(Smartgen::MarkupFile)).should == "do some rendering stuff"
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,128 @@
1
+ require 'spec_helper'
2
+
3
+ describe Smartgen::MarkupFile do
4
+ def path
5
+ fixture('src/common/index.textile')
6
+ end
7
+
8
+ subject { Smartgen::MarkupFile.new path }
9
+
10
+ describe "engine registration" do
11
+ before do
12
+ Smartgen::MarkupFile.engines.clear
13
+ end
14
+
15
+ after do
16
+ Smartgen::MarkupFile.engines.clear
17
+ end
18
+
19
+ it "should register textile engine by default" do
20
+ Smartgen::MarkupFile.engines.one? { |engine| engine.instance_of?(Smartgen::Engine::Textile) }.should be_true, "Textile was not registered as engine"
21
+ end
22
+
23
+ it "should register markdown engine by default" do
24
+ Smartgen::MarkupFile.engines.one? { |engine| engine.instance_of?(Smartgen::Engine::Markdown) }.should be_true, "Markdown was not registered as engine"
25
+ end
26
+
27
+ class MyEngine < Smartgen::Engine::Base
28
+ protected
29
+ def parse(body)
30
+ "some processing"
31
+ end
32
+
33
+ def extensions
34
+ ['.something', '.otherext']
35
+ end
36
+ end
37
+
38
+ it "should register an engine" do
39
+ Smartgen::MarkupFile.register(MyEngine)
40
+ Smartgen::MarkupFile.engines.one? { |engine| engine.instance_of?(MyEngine) }.should be_true, "MyEngine was not registered as engine"
41
+ end
42
+
43
+ it "should register the engine with high priority" do
44
+ Smartgen::MarkupFile.register(MyEngine)
45
+ Smartgen::MarkupFile.engines.first.should be_an_instance_of(MyEngine)
46
+ end
47
+ end
48
+
49
+ describe "attributes" do
50
+ it "should have a file path" do
51
+ subject.path.should == path
52
+ end
53
+
54
+ it "should have a filename" do
55
+ subject.filename.should == File.basename(path, File.extname(path))
56
+ end
57
+
58
+ it "should have an extension" do
59
+ subject.extension.should == File.extname(path)
60
+ end
61
+ end
62
+
63
+ describe "contents" do
64
+ it "should returns its raw contents" do
65
+ subject.raw_contents.should == File.read(path)
66
+ end
67
+
68
+ it "should return its contents" do
69
+ subject.contents.should == File.read(fixture('expectations/common/index.html'))
70
+ end
71
+ end
72
+
73
+ context "engines usage" do
74
+ context "using default engine" do
75
+ it "should use textile as markup engine when using defaults for files without extension" do
76
+ def path
77
+ fixture('src/common/somefile')
78
+ end
79
+
80
+ subject.engine.should be_an_instance_of(Smartgen::Engine::Textile)
81
+ end
82
+
83
+ it "should use the engine with the highest priority for files without extension" do
84
+ class MyEngine
85
+ def process(body)
86
+ "some processing"
87
+ end
88
+
89
+ def supported?(extension)
90
+ ['.something'].include?(extension)
91
+ end
92
+ end
93
+
94
+ def path
95
+ fixture('src/common/somefile')
96
+ end
97
+
98
+ Smartgen::MarkupFile.register(MyEngine)
99
+ subject.engine.should be_an_instance_of(MyEngine)
100
+ Smartgen::MarkupFile.engines.clear
101
+ end
102
+ end
103
+
104
+ context "using textile engine" do
105
+ it "should use textile as markup engine" do
106
+ subject.engine.should be_an_instance_of(Smartgen::Engine::Textile)
107
+ end
108
+ end
109
+
110
+ context "using markdown template" do
111
+ it "should use textile as markup engine for files with .markdown" do
112
+ def path
113
+ fixture('src/common/other_index.markdown')
114
+ end
115
+
116
+ subject.engine.should be_an_instance_of(Smartgen::Engine::Markdown)
117
+ end
118
+
119
+ it "should use textile as markup engine for files with .md" do
120
+ def path
121
+ fixture('src/common/other_index.md')
122
+ end
123
+
124
+ subject.engine.should be_an_instance_of(Smartgen::Engine::Markdown)
125
+ end
126
+ end
127
+ end
128
+ end