smartgen 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog.md +14 -0
- data/Gemfile.lock +2 -2
- data/README.md +7 -0
- data/lib/smartgen/configuration.rb +1 -49
- data/lib/smartgen/engines.rb +1 -0
- data/lib/smartgen/engines/base.rb +3 -3
- data/lib/smartgen/engines/erb.rb +15 -0
- data/lib/smartgen/engines/markdown.rb +1 -1
- data/lib/smartgen/engines/textile.rb +1 -1
- data/lib/smartgen/generator.rb +29 -17
- data/lib/smartgen/markup_file.rb +6 -2
- data/lib/smartgen/object_hash.rb +15 -5
- data/lib/smartgen/rake_task.rb +21 -5
- data/lib/smartgen/renderers/erb.rb +1 -4
- data/lib/smartgen/resource.rb +1 -9
- data/lib/smartgen/version.rb +1 -1
- data/spec/fixtures/expectations/common/another_index.html +13 -0
- data/spec/fixtures/expectations/common/index.html +8 -0
- data/spec/fixtures/expectations/common/other_index.html +13 -0
- data/spec/fixtures/expectations/erb/index.html +15 -0
- data/spec/fixtures/expectations/erb/with_layout/index.html +19 -0
- data/spec/fixtures/expectations/indexer/index_with_indexer.html +16 -0
- data/spec/fixtures/expectations/indexer/index_with_indexer_and_numbered_index.html +16 -0
- data/spec/fixtures/expectations/with_layout/index.html +12 -0
- data/spec/fixtures/expectations/with_layout/index_with_metadata.html +43 -0
- data/spec/fixtures/expectations/with_layout/index_with_specific_metadata.html +44 -0
- data/spec/fixtures/src/assets/images/image.gif +0 -0
- data/spec/fixtures/src/assets/javascripts/somelib.js +2 -0
- data/spec/fixtures/src/assets/stylesheets/style.css +2 -0
- data/spec/fixtures/src/common/another_index.md +12 -0
- data/spec/fixtures/src/common/index.textile +10 -0
- data/spec/fixtures/src/common/other_index.markdown +12 -0
- data/spec/fixtures/src/common/somefile +10 -0
- data/spec/fixtures/src/erb/index.html.erb +7 -0
- data/spec/fixtures/src/erb/with_layout/index.html.erb +7 -0
- data/spec/fixtures/src/erb/with_layout/layout.html.erb +5 -0
- data/spec/fixtures/src/indexer/index_with_indexer.textile +26 -0
- data/spec/fixtures/src/indexer/index_with_indexer_and_numbered_index.textile +26 -0
- data/spec/fixtures/src/layout.html.erb +5 -0
- data/spec/fixtures/src/layout_with_metadata.html.erb +22 -0
- data/spec/fixtures/src/layout_with_specific_metadata.html.erb +23 -0
- data/spec/fixtures/src/metadata.yml +43 -0
- data/spec/fixtures/src/with_layout/index.textile +10 -0
- data/spec/fixtures/src/with_layout/index_with_specific_metadata.textile +10 -0
- data/spec/lib/smartgen/configuration_spec.rb +5 -0
- data/spec/lib/smartgen/engines/base_spec.rb +73 -0
- data/spec/lib/smartgen/engines/erb_spec.rb +37 -0
- data/spec/lib/smartgen/engines/markdown_spec.rb +23 -0
- data/spec/lib/smartgen/engines/textile_spec.rb +19 -0
- data/spec/lib/smartgen/generator_spec.rb +272 -0
- data/spec/lib/smartgen/indexer_spec.rb +122 -0
- data/spec/lib/smartgen/markup_file_spec.rb +168 -0
- data/spec/lib/smartgen/object_hash_spec.rb +91 -0
- data/spec/lib/smartgen/renderers/erb_spec.rb +32 -0
- data/spec/lib/smartgen/resource_spec.rb +73 -0
- data/spec/lib/smartgen/watcher_spec.rb +71 -0
- data/spec/lib/smartgen_spec.rb +18 -0
- data/spec/sandbox/.gitkeep +0 -0
- data/spec/spec_helper.rb +37 -0
- metadata +99 -13
@@ -0,0 +1,168 @@
|
|
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
|
+
context "when filename ends with .html" do
|
59
|
+
def path
|
60
|
+
fixture('src/erb/index.html.erb')
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should not have .html in filename" do
|
64
|
+
subject.filename.should == File.basename(path, ".html#{File.extname(path)}")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should have an extension" do
|
69
|
+
subject.extension.should == File.extname(path)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "contents" do
|
74
|
+
it "should returns its raw contents" do
|
75
|
+
subject.raw_contents.should == File.read(path)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should return its contents" do
|
79
|
+
subject.contents.should == File.read(fixture('expectations/common/index.html'))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "engines usage" do
|
84
|
+
context "using default engine" do
|
85
|
+
it "should use textile as markup engine when using defaults for files without extension" do
|
86
|
+
def path
|
87
|
+
fixture('src/common/somefile')
|
88
|
+
end
|
89
|
+
|
90
|
+
subject.engine.should be_an_instance_of(Smartgen::Engine::Textile)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should use the engine with the highest priority for files without extension" do
|
94
|
+
class MyEngine
|
95
|
+
def process(body, metadata={})
|
96
|
+
"some processing"
|
97
|
+
end
|
98
|
+
|
99
|
+
def supported?(extension)
|
100
|
+
['.something'].include?(extension)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def path
|
105
|
+
fixture('src/common/somefile')
|
106
|
+
end
|
107
|
+
|
108
|
+
Smartgen::MarkupFile.register(MyEngine)
|
109
|
+
subject.engine.should be_an_instance_of(MyEngine)
|
110
|
+
Smartgen::MarkupFile.engines.clear
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "using textile engine" do
|
115
|
+
it "should use textile as markup engine" do
|
116
|
+
subject.engine.should be_an_instance_of(Smartgen::Engine::Textile)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "using markdown engine" do
|
121
|
+
it "should use markdown as markup engine for files with .markdown" do
|
122
|
+
def path
|
123
|
+
fixture('src/common/other_index.markdown')
|
124
|
+
end
|
125
|
+
|
126
|
+
subject.engine.should be_an_instance_of(Smartgen::Engine::Markdown)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should use markdown as markup engine for files with .md" do
|
130
|
+
def path
|
131
|
+
fixture('src/common/another_index.md')
|
132
|
+
end
|
133
|
+
|
134
|
+
subject.engine.should be_an_instance_of(Smartgen::Engine::Markdown)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "using erb engine" do
|
139
|
+
it "should use markdown as markup engine for files with .md" do
|
140
|
+
def path
|
141
|
+
fixture('src/erb/index.html.erb')
|
142
|
+
end
|
143
|
+
|
144
|
+
subject.engine.should be_an_instance_of(Smartgen::Engine::ERB)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "indexer" do
|
150
|
+
subject { Smartgen::MarkupFile.new path, :indexer => true }
|
151
|
+
|
152
|
+
it "should be accessible when using indexer" do
|
153
|
+
subject.indexer.should be_an_instance_of(Smartgen::Indexer)
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should use indexer" do
|
157
|
+
mock_indexer = mock(Smartgen::Indexer, :result => 'result')
|
158
|
+
Smartgen::Indexer.should_receive(:new).and_return(mock_indexer)
|
159
|
+
subject
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should return indexer result as contents" do
|
163
|
+
mock_indexer = mock(Smartgen::Indexer, :result => 'result')
|
164
|
+
Smartgen::Indexer.should_receive(:new).and_return(mock_indexer)
|
165
|
+
subject.contents.should == 'result'
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Smartgen::ObjectHash do
|
4
|
+
it { should be_a_kind_of(HashWithIndifferentAccess) }
|
5
|
+
|
6
|
+
it "should be duped as an Smartgen::ObjectHash" do
|
7
|
+
subject.dup.should be_an_instance_of(Smartgen::ObjectHash)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should differentiate itself when its inspected" do
|
11
|
+
subject.inspect.should == "ObjectHash({})"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should respond to all of its keys" do
|
15
|
+
subject.merge!({:foo => 'foo', 'bar' => 'bar'})
|
16
|
+
|
17
|
+
subject.keys.each do |key|
|
18
|
+
should respond_to(key)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should respond to all of its keys with setter methods" do
|
23
|
+
subject.merge!({:foo => 'foo', 'bar' => 'bar'})
|
24
|
+
|
25
|
+
subject.keys.map { |k| "#{k}=" }.each do |key|
|
26
|
+
should respond_to(key)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "inexistent key" do
|
31
|
+
it "should not respond to" do
|
32
|
+
capture(:stderr) { subject.should_not respond_to("invalid_key") }
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return an empty ObjectHash" do
|
36
|
+
capture(:stderr) { subject.invalid_key.should be_an_instance_of(Smartgen::ObjectHash) }
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should print a warn" do
|
40
|
+
capture(:stderr) { subject.invalid_key }.should == "warning: key invalid_key not found on #{subject.inspect}\n"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should respond to ancestor methods" do
|
45
|
+
ancestor = Smartgen::ObjectHash.ancestors.first
|
46
|
+
ancestor.instance_methods.each do |method|
|
47
|
+
should respond_to(method)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should fetch key when calling method with the same name directly" do
|
52
|
+
subject.merge!({:foo => 'foo'})
|
53
|
+
subject.foo.should == 'foo'
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should set a new key when any setter method is called" do
|
57
|
+
subject.foo = 'foo'
|
58
|
+
subject.foo.should == 'foo'
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should update an existing key when setter method is called" do
|
62
|
+
subject.merge!({:foo => 'foo'})
|
63
|
+
subject.foo = 'bar'
|
64
|
+
subject.foo.should == 'bar'
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "nested hashes" do
|
68
|
+
subject { Smartgen::ObjectHash.new({:nested_hash => {:some_key => 'value'}})}
|
69
|
+
|
70
|
+
it "should accept calling nested methods" do
|
71
|
+
subject.nested_hash.some_key.should == 'value'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "nested array with hashes" do
|
76
|
+
subject { Smartgen::ObjectHash.new({:array => [{:some_key => 'value'}]})}
|
77
|
+
|
78
|
+
it "should accept calling nested methods" do
|
79
|
+
subject.array.first.some_key.should == 'value'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe Hash do
|
84
|
+
subject { Hash.new }
|
85
|
+
|
86
|
+
it "should return an object hash" do
|
87
|
+
subject.with_object_hash.should be_an_instance_of(Smartgen::ObjectHash)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Smartgen::Renderer::ERB do
|
4
|
+
def contents
|
5
|
+
"<p>Some HTML content</p>"
|
6
|
+
end
|
7
|
+
|
8
|
+
def markup_file
|
9
|
+
@markup_file ||= mock(Smartgen::MarkupFile, :contents => contents)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should render the given layout with markup_file variable" do
|
13
|
+
layout = "<html><body><%= markup_file.contents %></body></html>"
|
14
|
+
|
15
|
+
subject.render(layout, markup_file).should == "<html><body>#{contents}</body></html>"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should render the given layout with metadata variable" do
|
19
|
+
layout = "<html><body><%= markup_file.contents %><div><%= metadata[:some_key] %></div></body></html>"
|
20
|
+
subject.render(layout, markup_file, Smartgen::ObjectHash.new(:some_key => 'some_value')).should == "<html><body>#{contents}<div>some_value</div></body></html>"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should render the given layout with metadata variable, using methods instead of accessing keys" do
|
24
|
+
layout = "<html><body><%= markup_file.contents %><div><%= metadata.some_key %></div></body></html>"
|
25
|
+
subject.render(layout, markup_file, Smartgen::ObjectHash.new(:some_key => 'some_value')).should == "<html><body>#{contents}<div>some_value</div></body></html>"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should render the given layout with metadata variable, using nested methods instead of accessing keys" do
|
29
|
+
layout = "<html><body><%= markup_file.contents %><div><%= metadata.nested_hash.some_key %></div></body></html>"
|
30
|
+
subject.render(layout, markup_file, Smartgen::ObjectHash.new(:nested_hash => {:some_key => 'some_value'})).should == "<html><body>#{contents}<div>some_value</div></body></html>"
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Smartgen::Resource do
|
4
|
+
describe "configuration" do
|
5
|
+
it "should yield a configuration when configuring" do
|
6
|
+
subject.configure do |config|
|
7
|
+
config.should be_an_instance_of(Smartgen::Configuration)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should use the same configuration on later accesses" do
|
12
|
+
configuration = nil
|
13
|
+
subject.configure { |config| configuration = config }
|
14
|
+
|
15
|
+
subject.configure do |config|
|
16
|
+
config.should be_equal(configuration)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "generating" do
|
22
|
+
shared_examples_for "generation with configuration" do
|
23
|
+
let :expected_arguments do
|
24
|
+
[subject.config.src_files, subject.config.output_folder]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should generate files using the configuration" do
|
28
|
+
mock_generator = mock(Smartgen::Generator)
|
29
|
+
Smartgen::Generator.
|
30
|
+
should_receive(:new).
|
31
|
+
with(expected_arguments, expected_options).
|
32
|
+
and_return(mock_generator)
|
33
|
+
|
34
|
+
mock_generator.should_receive(:invoke_all)
|
35
|
+
subject.generate!
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "with default options" do
|
40
|
+
let :expected_options do
|
41
|
+
Smartgen::ObjectHash.new
|
42
|
+
end
|
43
|
+
|
44
|
+
it_should_behave_like "generation with configuration"
|
45
|
+
end
|
46
|
+
|
47
|
+
context "with customized options" do
|
48
|
+
before do
|
49
|
+
subject.configure do |c|
|
50
|
+
c.src_files = ['help/**/*', 'ChangeLog', 'doc_src/**/*']
|
51
|
+
c.output_folder = 'public/docs'
|
52
|
+
c.layout = 'doc_src/layout.html.erb'
|
53
|
+
c.assets = ['doc_src/javascript/*.js', 'doc_src/stylesheets/*.css', 'doc_src/images/*.*']
|
54
|
+
c.metadata_file = 'doc_src/metadata.yml'
|
55
|
+
c.some_other_option = true
|
56
|
+
c.and_another_one = 'some-value'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
let :expected_options do
|
61
|
+
Smartgen::ObjectHash.new({
|
62
|
+
:layout => subject.config.layout,
|
63
|
+
:assets => subject.config.assets,
|
64
|
+
:metadata_file => subject.config.metadata_file,
|
65
|
+
:some_other_option => subject.config.some_other_option,
|
66
|
+
:and_another_one => subject.config.and_another_one
|
67
|
+
})
|
68
|
+
end
|
69
|
+
|
70
|
+
it_should_behave_like "generation with configuration"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Smartgen::Watcher do
|
4
|
+
it "should create a resource and yield its configuration" do
|
5
|
+
expected_config = nil
|
6
|
+
Smartgen::Watcher.new(:my_resource) { |config| expected_config = config }
|
7
|
+
expected_config.should == Smartgen[:my_resource].config
|
8
|
+
end
|
9
|
+
|
10
|
+
context "when it will start watching" do
|
11
|
+
def src_files
|
12
|
+
['doc/**/*']
|
13
|
+
end
|
14
|
+
|
15
|
+
def directory_watcher
|
16
|
+
return @directory_watcher if @directory_watcher
|
17
|
+
|
18
|
+
@directory_watcher = mock(DirectoryWatcher, :add_observer => 'observer', :interval= => '2')
|
19
|
+
@directory_watcher.stub!(:start).and_return(@directory_watcher)
|
20
|
+
@directory_watcher.stub!(:join).and_return(@directory_watcher)
|
21
|
+
@directory_watcher
|
22
|
+
end
|
23
|
+
|
24
|
+
before do
|
25
|
+
DirectoryWatcher.stub!(:new).and_return(directory_watcher)
|
26
|
+
end
|
27
|
+
|
28
|
+
subject do
|
29
|
+
Smartgen::Watcher.new(:my_resource) do |config|
|
30
|
+
config.src_files = src_files
|
31
|
+
config.output_folder = 'public/docs'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should create a directory watcher, pre loading src_files" do
|
36
|
+
DirectoryWatcher.should_receive(:new).with('.', :glob => src_files).and_return(directory_watcher)
|
37
|
+
capture(:stdout) { subject.start }
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should add itself as an observer, with :generate method as the callback" do
|
41
|
+
directory_watcher.should_receive(:add_observer).with(subject, :generate)
|
42
|
+
capture(:stdout) { subject.start }
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should start watching" do
|
46
|
+
directory_watcher.should_receive(:start)
|
47
|
+
directory_watcher.should_receive(:join)
|
48
|
+
capture(:stdout) { subject.start }
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should set interval to 2 seconds" do
|
52
|
+
directory_watcher.should_receive(:interval=).with(2)
|
53
|
+
capture(:stdout) { subject.start }
|
54
|
+
end
|
55
|
+
|
56
|
+
context "when generating" do
|
57
|
+
it "should generate files" do
|
58
|
+
Smartgen[:my_resource].should_receive(:generate!)
|
59
|
+
capture(:stdout) { subject.generate }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when user hits ctrl+c" do
|
64
|
+
it "should exit gracefully" do
|
65
|
+
directory_watcher.should_receive(:stop)
|
66
|
+
Kernel.should_receive(:trap).with('INT').and_yield
|
67
|
+
capture(:stdout) { subject.start }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Smartgen do
|
5
|
+
describe "resources" do
|
6
|
+
it "should create a resource the first time it is accessed" do
|
7
|
+
Smartgen[:foo].should be_an_instance_of(Smartgen::Resource)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should use the same resource when it is accessed in the future" do
|
11
|
+
Smartgen[:foo].should be_equal(Smartgen[:foo])
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should create different resource for each given name" do
|
15
|
+
Smartgen[:foo].should_not be_equal(Smartgen[:bar])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|