retter 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/.travis.yml +1 -1
  2. data/ChangeLog.md +10 -0
  3. data/README.md +1 -3
  4. data/bin/retter +8 -4
  5. data/lib/retter/binder.rb +50 -0
  6. data/lib/retter/command.rb +42 -39
  7. data/lib/retter/config.rb +24 -23
  8. data/lib/retter/entries.rb +14 -18
  9. data/lib/retter/entry.rb +52 -29
  10. data/lib/retter/generator/base.rb +6 -7
  11. data/lib/retter/generator/skel/Gemfile +1 -2
  12. data/lib/retter/generator/skel/Retterfile +2 -2
  13. data/lib/retter/generator/skel/layouts/article.html.haml +3 -2
  14. data/lib/retter/generator/skel/layouts/entry.html.haml +3 -2
  15. data/lib/retter/generator/skel/layouts/index.html.haml +4 -2
  16. data/lib/retter/generator.rb +0 -1
  17. data/lib/retter/{renderers.rb → markdown.rb} +22 -1
  18. data/lib/retter/page/article.rb +54 -0
  19. data/lib/retter/page/base.rb +97 -0
  20. data/lib/retter/page/entries.rb +17 -0
  21. data/lib/retter/page/entry.rb +46 -0
  22. data/lib/retter/page/feed.rb +63 -0
  23. data/lib/retter/page/index.rb +17 -0
  24. data/lib/retter/page/profile.rb +17 -0
  25. data/lib/retter/page/view_helper.rb +9 -1
  26. data/lib/retter/page.rb +22 -74
  27. data/lib/retter/preprint.rb +19 -10
  28. data/lib/retter/version.rb +1 -1
  29. data/lib/retter.rb +41 -29
  30. data/retter.gemspec +44 -53
  31. data/spec/command/callback_spec.rb +16 -6
  32. data/spec/command/clean_spec.rb +20 -0
  33. data/spec/command/commit_spec.rb +11 -12
  34. data/spec/command/edit_spec.rb +28 -38
  35. data/spec/command/list_spec.rb +4 -4
  36. data/spec/command/open_spec.rb +2 -2
  37. data/spec/command/preview_spec.rb +7 -12
  38. data/spec/command/rebind_spec.rb +143 -66
  39. data/spec/spec_helper.rb +10 -3
  40. data/spec/support/example_group_helper.rb +55 -15
  41. data/spec/support/matchers.rb +0 -1
  42. metadata +195 -78
  43. data/lib/retter/generator/updator.rb +0 -7
  44. data/lib/retter/pages/article.rb +0 -41
  45. data/lib/retter/pages/entries.rb +0 -15
  46. data/lib/retter/pages/entry.rb +0 -35
  47. data/lib/retter/pages/feed.rb +0 -51
  48. data/lib/retter/pages/index.rb +0 -15
  49. data/lib/retter/pages/profile.rb +0 -15
  50. data/lib/retter/pages.rb +0 -77
  51. data/spec/command/invoke_after_spec.rb +0 -29
  52. data/spec/fixtures/sample.md +0 -295
@@ -4,11 +4,8 @@ require 'spec_helper'
4
4
 
5
5
  describe 'Retter::Command#rebind', clean: :all do
6
6
  context 'first post' do
7
- let(:date_str) { '20110101' }
8
- let(:date) { Date.parse(date_str) }
9
- let(:date_file) { Retter.entries.retter_file(date) }
10
- let(:date_html) { Retter::Pages.entry_file(date) }
11
- let(:article) { <<-EOM }
7
+ let(:date_str) { '2011/01/01' }
8
+ let(:article) { <<-EOM }
12
9
  # 朝11時
13
10
 
14
11
  おはようございます
@@ -19,13 +16,14 @@ describe 'Retter::Command#rebind', clean: :all do
19
16
  EOM
20
17
 
21
18
  before do
22
- stub_time date_str
19
+ time_travel_to date_str
23
20
 
24
- wip_file.open('w') {|f| f.puts article }
21
+ write_to_wip_file article
25
22
 
26
- command.should_receive(:invoke_after).with(:bind)
27
- command.should_receive(:invoke_after).with(:rebind)
28
- command.rebind
23
+ command.should_receive(:after_callback).with(:bind)
24
+ command.should_receive(:after_callback).with(:rebind)
25
+
26
+ invoke_command :rebind
29
27
  end
30
28
 
31
29
  describe 'wip file' do
@@ -35,80 +33,80 @@ describe 'Retter::Command#rebind', clean: :all do
35
33
  end
36
34
 
37
35
  describe 'index.html' do
38
- let(:index_html) { Retter.config.retter_home.join('index.html').read }
36
+ let(:index_html) { generated_file('index.html').read }
39
37
 
40
- it { texts_of(index_html, 'article p').should include('おはようございます') }
38
+ it { texts_of(index_html, 'article p').should include 'おはようございます' }
41
39
  it { texts_of(index_html, 'article h1.date').should == %w(2011-01-01) }
42
- it { texts_of(index_html, 'article h1').should == %w(2011-01-01 朝11時 夜1時) }
40
+ it { texts_of(index_html, 'article h1').should == %w(2011-01-01 朝11時 夜1時) }
43
41
  end
44
42
 
45
43
  describe 'entries.html' do
46
- let(:entries_html) { Retter.config.retter_home.join('entries.html').read }
44
+ let(:entries_html) { generated_file('entries.html').read }
47
45
 
48
46
  it { texts_of(entries_html, 'a.entry').first.should == '01/01' }
49
- it { texts_of(entries_html, 'a.article').should == %w(朝11時 夜1時) }
47
+ it { texts_of(entries_html, 'a.article').should == %w(朝11時 夜1時) }
50
48
  end
51
49
 
52
50
  describe 'entry.html' do
53
- let(:entry_html) { Retter::Pages.entry_file(date).read }
51
+ let(:entry_html) { entry_html_file(date_str).read }
54
52
 
55
- it { texts_of(entry_html, 'article p').should == %w(おはようございます おやすみなさい) }
53
+ it { texts_of(entry_html, 'article p').should == %w(おはようございます おやすみなさい) }
56
54
  it { texts_of(entry_html, 'article h1.date').should == %w(2011-01-01) }
57
- it { texts_of(entry_html, 'article h1').should == %w(2011-01-01 朝11時 夜1時) }
55
+ it { texts_of(entry_html, 'article h1').should == %w(2011-01-01 朝11時 夜1時) }
58
56
  end
59
57
 
60
- describe 'entry part(first)' do
61
- let(:part_html) { Retter::Pages.entry_dir(date).join('a0.html').read }
58
+ describe 'article (first)' do
59
+ let(:article_html) { article_html_file(date_str, 'a0').read }
62
60
 
63
61
  describe 'body' do
64
- subject { texts_of(part_html, 'article p') }
62
+ subject { texts_of(article_html, 'article p') }
65
63
 
66
- it { should include('おはようございます') }
67
- it { should_not include('おやすみなさい') }
64
+ it { should include 'おはようございます' }
65
+ it { should_not include 'おやすみなさい' }
68
66
  end
69
67
 
70
68
  describe 'date' do
71
- subject { texts_of(part_html, 'article h1.date') }
69
+ subject { texts_of(article_html, 'article h1.date') }
72
70
 
73
71
  it { should == %w(2011-01-01) }
74
72
  end
75
73
 
76
74
  describe 'headings' do
77
- subject { texts_of(part_html, 'article h1') }
75
+ subject { texts_of(article_html, 'article h1') }
78
76
 
79
- it { should include('朝11時') }
80
- it { should_not include('夜1時') }
77
+ it { should include '朝11時' }
78
+ it { should_not include '夜1時' }
81
79
  end
82
80
  end
83
81
 
84
- describe 'entry part(last)' do
85
- let(:part_html) { Retter::Pages.entry_dir(date).join('a1.html').read }
82
+ describe 'article (last)' do
83
+ let(:article_html) { article_html_file(date_str, 'a1').read }
86
84
 
87
85
  describe 'body' do
88
- subject { texts_of(part_html, 'article p') }
86
+ subject { texts_of(article_html, 'article p') }
89
87
 
90
- it { should include('おやすみなさい') }
91
- it { should_not include('おはようございます') }
88
+ it { should include 'おやすみなさい' }
89
+ it { should_not include 'おはようございます' }
92
90
  end
93
91
 
94
92
  describe 'date' do
95
- subject { texts_of(part_html, 'article h1.date') }
93
+ subject { texts_of(article_html, 'article h1.date') }
96
94
 
97
95
  it { should == %w(2011-01-01) }
98
96
  end
99
97
 
100
98
  describe 'headings' do
101
- subject { texts_of(part_html, 'article h1') }
99
+ subject { texts_of(article_html, 'article h1') }
102
100
 
103
- it { should include('夜1時') }
104
- it { should_not include('朝11時') }
101
+ it { should include '夜1時' }
102
+ it { should_not include '朝11時' }
105
103
  end
106
104
  end
107
105
  end
108
106
 
109
- context 'includes code block' do
110
- let(:index_html) { Retter.config.retter_home.join('index.html').read }
111
- let(:article) { <<-EOM }
107
+ context 'article includes code block' do
108
+ let(:index_html) { generated_file('index.html').read }
109
+ let(:article) { <<-EOM }
112
110
  # コードを書きました
113
111
 
114
112
  ```ruby
@@ -117,13 +115,14 @@ sleep 1000
117
115
  EOM
118
116
 
119
117
  before do
120
- wip_file.open('w') {|f| f.puts article }
118
+ write_to_wip_file article
121
119
  end
122
120
 
123
121
  context 'use Pygments' do
124
122
  before do
125
- Retter.config.renderer Retter::Renderers::PygmentsRenderer
126
- command.rebind
123
+ Retter::Site.config.renderer Retter::Markdown::PygmentsRenderer
124
+
125
+ invoke_command :rebind
127
126
  end
128
127
 
129
128
  specify 'code should be highlighted' do
@@ -133,8 +132,9 @@ sleep 1000
133
132
 
134
133
  context 'use CodeRay' do
135
134
  before do
136
- Retter.config.renderer Retter::Renderers::CodeRayRenderer
137
- command.rebind
135
+ Retter::Site.config.renderer Retter::Markdown::CodeRayRenderer
136
+
137
+ invoke_command :rebind
138
138
  end
139
139
 
140
140
  specify 'code should be highlighted' do
@@ -143,57 +143,134 @@ sleep 1000
143
143
  end
144
144
  end
145
145
 
146
- context 'with silent option' do
146
+ context 'use custom markup' do
147
+ let(:index_html) { generated_file('index.html').read }
148
+ let(:custom_markup) { Object.new.tap {|o| o.define_singleton_method(:render, &:upcase) } }
149
+
147
150
  before do
148
- wip_file.open('w') {|f| f.puts 'article' }
151
+ Retter::Site.config.markup custom_markup
152
+
153
+ write_to_wip_file 'hi'
154
+
155
+ invoke_command :rebind
156
+ end
157
+
158
+ after do
159
+ Retter::Entries.instance_variable_set :@markup, nil
160
+ end
161
+
162
+ subject { texts_of(index_html, 'article p') }
163
+
164
+ it { should include 'HI' }
165
+ end
149
166
 
150
- command.stub!(:options) { {silent: true} }
167
+ context 'with silent option' do
168
+ before do
169
+ write_to_wip_file 'article'
151
170
  end
152
171
 
153
172
  specify 'rebind callback should not invoked' do
154
- command.should_not_receive(:invoke_after)
173
+ command.should_not_receive(:after_callback)
155
174
 
156
- command.rebind
175
+ invoke_command :rebind, silent: true
157
176
  end
158
177
  end
159
178
 
160
179
  context 'skipping some singleton pages binding' do
161
- let(:retter_home) { Retter.config.retter_home }
162
- let(:index_html) { retter_home.join('index.html') }
163
- let(:profile_html) { retter_home.join('profile.html') }
164
- let(:entries_html) { retter_home.join('entries.html') }
165
- let(:feed_file) { retter_home.join('feed.rss') }
180
+ let(:index_html) { generated_file('index.html') }
181
+ let(:profile_html) { generated_file('profile.html') }
182
+ let(:entries_html) { generated_file('entries.html') }
183
+ let(:feed_file) { generated_file('feed.rss') }
166
184
 
167
185
  before do
168
186
  index_html.unlink
169
187
 
170
- command.edit
188
+ invoke_command :edit
171
189
  end
172
190
 
173
191
  context 'skipping all' do
174
192
  before do
175
- Retter::Pages.allow_binding :none
176
-
177
- command.rebind
193
+ invoke_command :rebind do |config|
194
+ config.allow_binding :none
195
+ end
178
196
  end
179
197
 
180
198
  it { profile_html.should_not be_exist }
181
199
  it { entries_html.should_not be_exist }
182
- it { feed_file.should_not be_exist }
183
- it { index_html.should be_exist }
200
+ it { feed_file.should_not be_exist }
201
+ it { index_html.should be_exist }
184
202
  end
185
203
 
186
204
  context 'skipping only :feed' do
187
205
  before do
188
- Retter::Pages.allow_binding [:profile, :entries]
189
-
190
- command.rebind
206
+ invoke_command :rebind do |config|
207
+ config.allow_binding [:profile, :entries]
208
+ end
191
209
  end
192
210
 
193
- it { profile_html.should be_exist }
194
- it { entries_html.should be_exist }
211
+ it { profile_html.should be_exist }
212
+ it { entries_html.should be_exist }
195
213
  it { feed_file.should_not be_exist }
196
- it { index_html.should be_exist }
214
+ it { index_html.should be_exist }
215
+ end
216
+ end
217
+
218
+ context 'with link or image' do
219
+ let(:index_html) { generated_file('index.html').read }
220
+ let(:elements) { nokogiri(index_html) }
221
+
222
+ before do
223
+ write_to_wip_file article
224
+
225
+ invoke_command :rebind
226
+ end
227
+
228
+ describe 'a href="//example.com/foo/bar"' do
229
+ let(:article) { '[title](//example.com/foo/bar)' }
230
+
231
+ it { elements.search("a[href='//example.com/foo/bar']").should_not be_empty }
232
+ end
233
+
234
+ describe 'img src="//example.com/foo/bar.png"' do
235
+ let(:article) { '![title](//example.com/foo/bar.png)' }
236
+
237
+ it { elements.search("img[src='//example.com/foo/bar.png']").should_not be_empty }
238
+ end
239
+
240
+ describe 'a href="/foo/bar"' do
241
+ let(:article) { '[title](/foo/bar)' }
242
+
243
+ it { elements.search("a[href='./foo/bar']").should_not be_empty }
244
+ end
245
+
246
+ describe 'img src="/foo/bar.png"' do
247
+ let(:article) { '![title](/foo/bar.png)' }
248
+
249
+ it { elements.search("img[src='./foo/bar.png']").should_not be_empty }
250
+ end
251
+
252
+ describe 'a href="./foo/bar"' do
253
+ let(:article) { '[title](./foo/bar)' }
254
+
255
+ it { elements.search("a[href='./foo/bar']").should_not be_empty }
256
+ end
257
+
258
+ describe 'img src="./foo/bar.png"' do
259
+ let(:article) { '![title](./foo/bar.png)' }
260
+
261
+ it { elements.search("img[src='./foo/bar.png']").should_not be_empty }
262
+ end
263
+
264
+ describe 'a href="../foo/bar"' do
265
+ let(:article) { '[title](../foo/bar)' }
266
+
267
+ it { elements.search("a[href='../foo/bar']").should_not be_empty }
268
+ end
269
+
270
+ describe 'img src="../foo/bar.png"' do
271
+ let(:article) { '![title](../foo/bar.png)' }
272
+
273
+ it { elements.search("img[src='../foo/bar.png']").should_not be_empty }
197
274
  end
198
275
  end
199
276
  end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # coding: utf-8
2
2
 
3
3
  require 'tapp'
4
+ require 'delorean'
4
5
 
5
6
  if ENV['COVERAGE']
6
7
  require 'simplecov'
@@ -26,13 +27,19 @@ RSpec.configure do |config|
26
27
 
27
28
  config.after :each, clean: :all do
28
29
  FileUtils.rm_rf retter_home
29
- Retter.reset!
30
+
31
+ Retter::Site.reset!
30
32
  end
31
33
 
32
- config.before do
34
+ config.before :each do
33
35
  env = {'EDITOR' => fake_editor.to_path, 'RETTER_HOME' => RETTER_ROOT.join('tmp', 'test').to_s}
34
36
 
35
- Retter.load env
37
+ Retter::Site.load env
38
+ end
39
+
40
+ config.include Delorean
41
+ config.after :each do
42
+ back_to_the_present
36
43
  end
37
44
 
38
45
  config.include ExampleGroupHelper
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
 
3
- require 'time'
4
3
  require 'nokogiri'
4
+ require 'stringio'
5
5
 
6
6
  module ExampleGroupHelper
7
7
  module RetterShortcuts
@@ -9,8 +9,58 @@ module ExampleGroupHelper
9
9
  @command ||= Retter::Command.new
10
10
  end
11
11
 
12
+ def invoke_command(command_name, *args)
13
+ @command ||= Retter::Command.new
14
+
15
+ yield Retter::Site.config if block_given?
16
+
17
+ if args.last.is_a?(Hash)
18
+ options = args.pop
19
+
20
+ @command.stub!(:options) { options }
21
+ end
22
+
23
+ @command.__send__ command_name, *args
24
+ end
25
+
12
26
  def wip_file
13
- Retter.entries.wip_file
27
+ Retter::Site.entries.wip_file
28
+ end
29
+
30
+ def write_to_wip_file(body)
31
+ wip_file.open('w') {|f| f.write body }
32
+ end
33
+
34
+ def generated_file(path)
35
+ Retter::Site.config.retter_home.join(path)
36
+ end
37
+
38
+ def markdown_file(date)
39
+ date = date_wrap(date)
40
+
41
+ Retter::Site.entries.retter_file(date)
42
+ end
43
+
44
+ def find_entry_by_string(str)
45
+ Retter::Site.entries.detect_by_string(str)
46
+ end
47
+
48
+ def entry_html_file(date)
49
+ date = date_wrap(date)
50
+
51
+ Retter::Page.entry_file(date)
52
+ end
53
+
54
+ def article_html_file(date, id)
55
+ date = date_wrap(date)
56
+
57
+ Retter::Page.entry_dir(date).join("#{id}.html")
58
+ end
59
+
60
+ private
61
+
62
+ def date_wrap(str)
63
+ Date.parse(str.to_s)
14
64
  end
15
65
  end
16
66
 
@@ -29,30 +79,20 @@ module ExampleGroupHelper
29
79
  module Stream
30
80
  def capture(stream)
31
81
  begin
32
- stream = stream.to_s
33
82
  eval "$#{stream} = StringIO.new"
83
+
34
84
  yield
85
+
35
86
  result = eval("$#{stream}").string
36
87
  ensure
37
- eval("$#{stream} = #{stream.upcase}")
88
+ eval %($#{stream} = #{stream.upcase})
38
89
  end
39
90
 
40
91
  result
41
92
  end
42
93
  end
43
94
 
44
- module StubTime
45
- def stub_time(time_str)
46
- date = Date.parse(time_str)
47
- time = Time.parse(time_str)
48
-
49
- Date.stub!(:today).and_return(date)
50
- Time.stub!(:now).and_return(time)
51
- end
52
- end
53
-
54
95
  include RetterShortcuts
55
96
  include HTML
56
97
  include Stream
57
- include StubTime
58
98
  end
@@ -5,4 +5,3 @@ RSpec::Matchers.define :written do
5
5
  file.exist? && !file.size.zero?
6
6
  end
7
7
  end
8
-