smartgen 0.1.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.
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