wikilink-converter 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.
@@ -0,0 +1,43 @@
1
+ RSpec::Matchers.define :convert do |*from|
2
+ from_description = from
3
+ from_description = nil if from.empty?
4
+ from_description = from.first if from.size == 1
5
+
6
+ diffable
7
+
8
+ define_method :actual do
9
+ @real_actual ||= @actual.call(*from)
10
+ end
11
+
12
+ def expected
13
+ [@to]
14
+ end
15
+
16
+ match do |method|
17
+ actual == @to
18
+ end
19
+
20
+ description do
21
+ "convert #{from_description.inspect} to #{@to.inspect}"
22
+ end
23
+
24
+ failure_message_for_should do |method|
25
+ <<MESSAGE
26
+ expected #{from_description.inspect}
27
+ to #{@to.inspect}
28
+ got #{actual.inspect}
29
+ MESSAGE
30
+ end
31
+
32
+ failure_message_for_should_not do |method|
33
+ <<MESSAGE
34
+ expected #{from_description.inspect}
35
+ not to #{@to.inspect}
36
+ got #{actual.inspect}
37
+ MESSAGE
38
+ end
39
+
40
+ chain :to do |to|
41
+ @to = to
42
+ end
43
+ end
@@ -0,0 +1,113 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ shared_examples 'converter that can forward to given block' do |klass|
4
+ klass ||= describes
5
+
6
+ context 'given block through #config' do
7
+ let(:converter) { klass.new.config { 'it works' } }
8
+
9
+ describe '#run' do
10
+ subject { converter.method(:run) }
11
+ it 'forwards to the block' do
12
+ subject.should convert(':', 'Home', 'Home', '/').to('it works')
13
+ end
14
+ end
15
+ end
16
+
17
+ context 'given block accessing options in constructor through #config' do
18
+ let(:converter) {
19
+ klass.new(fake_result: 'fake').config { options[:fake_result] }
20
+ }
21
+
22
+ describe '#run' do
23
+ subject { converter.method(:run) }
24
+ it 'forwards to the block and allows options access' do
25
+ subject.should convert(':', 'Home', 'Home', '/').to('fake')
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ describe Wikilink::Converter::Namespace do
32
+ let(:converter) { Wikilink::Converter::Namespace.new }
33
+ describe '#run' do
34
+ subject { converter.method(:run) }
35
+ it 'does nothing' do
36
+ subject.should convert(':', 'Home', 'Home', '/').to(nil)
37
+ end
38
+ end
39
+
40
+ it_behaves_like 'converter that can forward to given block'
41
+ end
42
+
43
+ describe Wikilink::Converter::Namespace::Default do
44
+ shared_examples 'converter that keeps query fragment only path untouched' do
45
+ it { should convert(':', '#toc-1', 'Header 1', '/').
46
+ to('<a href="#toc-1">Header 1</a>')
47
+ }
48
+ it { should convert(':', '?q=keyword', 'Search keyword', '/').
49
+ to('<a href="?q=keyword">Search keyword</a>')
50
+ }
51
+ it { should convert(':', '?q=keyword#page-10', 'Search keyword (page 10)', '/').
52
+ to('<a href="?q=keyword#page-10">Search keyword (page 10)</a>')
53
+ }
54
+ end
55
+
56
+ let(:converter) { self.class.describes.new }
57
+ describe '#run' do
58
+ subject { converter.method(:run) }
59
+ it { should convert(':', 'Home', 'Name', '/').
60
+ to('<a href="Home">Name</a>')
61
+ }
62
+ it_behaves_like 'converter that keeps query fragment only path untouched'
63
+ end
64
+
65
+ context 'given option :prefix "/wiki/"' do
66
+ let(:converter) { self.class.describes.new prefix: '/wiki/' }
67
+ describe '#run' do
68
+ subject { converter.method(:run) }
69
+ it_behaves_like 'converter that keeps query fragment only path untouched'
70
+ end
71
+ end
72
+
73
+ context 'given option :suffix "/index.html"' do
74
+ let(:converter) { self.class.describes.new suffix: '/index.html' }
75
+ describe '#run' do
76
+ subject { converter.method(:run) }
77
+ it { should convert(':', 'Home', 'Name', '/').
78
+ to('<a href="Home/index.html">Name</a>')
79
+ }
80
+ it_behaves_like 'converter that keeps query fragment only path untouched'
81
+ end
82
+ end
83
+
84
+ context 'given option :external true' do
85
+ let(:converter) { self.class.describes.new external: true }
86
+ describe '#run' do
87
+ subject { converter.method(:run) }
88
+ it { should convert(':', 'Home', 'Name', '/').
89
+ to('<a class="external" href="Home">Name</a>')
90
+ }
91
+ end
92
+ end
93
+ context 'given option :class "fancy"' do
94
+ let(:converter) { self.class.describes.new class: 'fancy' }
95
+ describe '#run' do
96
+ subject { converter.method(:run) }
97
+ it { should convert(':', 'Home', 'Name', '/').
98
+ to('<a class="fancy" href="Home">Name</a>')
99
+ }
100
+ end
101
+ end
102
+ context 'given option :external true and :class "fancy"' do
103
+ let(:converter) { self.class.describes.new external: true, class: 'fancy' }
104
+ describe '#run' do
105
+ subject { converter.method(:run) }
106
+ it { should convert(':', 'Home', 'Name', '/').
107
+ to('<a class="fancy external" href="Home">Name</a>')
108
+ }
109
+ end
110
+ end
111
+
112
+ it_behaves_like 'converter that can forward to given block'
113
+ end
@@ -0,0 +1,334 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ describe Wikilink::Converter::Site do
4
+ DEFAULT_NAMESPACE = Wikilink::Converter::Site::DEFAULT_NAMESPACE
5
+ CURRENT_SITE_NAME = Wikilink::Converter::Site::CURRENT_SITE_NAME
6
+
7
+ # { subject.foo }.should forward(:bar).to(handler).with(any_args)
8
+ RSpec::Matchers.define :forward do |message|
9
+ match do |block|
10
+ block.call
11
+ @handler.received_message?(message, *@arguments)
12
+ end
13
+
14
+ description do
15
+ "forward to message #{message} to #{@handler.inspect}"
16
+ end
17
+
18
+ failure_message_for_should do |block|
19
+ <<MESSAGE
20
+ expected forward #{message}
21
+ to #{block}
22
+ with #{@arguments.inspect}
23
+ MESSAGE
24
+ end
25
+
26
+ failure_message_for_should_not do |block|
27
+ <<MESSAGE
28
+ expected not forward #{message}
29
+ to #{block}
30
+ with #{@arguments.inspect}
31
+ MESSAGE
32
+ end
33
+
34
+ chain :with do |*arguments|
35
+ @arguments = arguments
36
+ end
37
+
38
+ chain :to do |handler|
39
+ @handler = handler
40
+ end
41
+ end
42
+
43
+ shared_examples 'configuring a new instance of class as namespace handler' do |namespace|
44
+ # require setting converter to an instance of Site
45
+ context 'with converter class' do
46
+ class SpecNamespace; end
47
+ define_method :call do |*args|
48
+ if namespace.to_s.empty?
49
+ converter.on_namespace SpecNamespace, *args
50
+ else
51
+ converter.on_namespace namespace, SpecNamespace, *args
52
+ end
53
+ end
54
+ let(:namespace_converter) { double(:namespace_converter) }
55
+
56
+ it 'creates a new instance of the specified class' do
57
+ SpecNamespace.should_receive(:new).once
58
+ call
59
+ end
60
+
61
+ it 'uses the instance of the class as new namespace converter' do
62
+ SpecNamespace.should_receive(:new).once.and_return(namespace_converter)
63
+ call
64
+ namespace_converter.should_receive(:run).and_return('it works')
65
+ converter.run(':', namespace, 'Home', 'Name', '/').should eq('it works')
66
+ end
67
+
68
+ context 'and options' do
69
+ let(:options) { { foo: :bar} }
70
+ it 'creates a new instance of the specified class and options' do
71
+ SpecNamespace.should_receive(:new).once
72
+ call options
73
+ end
74
+
75
+ it 'initializes the new instance of the specified class with options' do
76
+ SpecNamespace.should_receive(:new).with(hash_including(foo: :bar)).once
77
+ call options
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ let(:default_namespace) { double(:default_namespace).as_null_object }
84
+ let(:namespace) { double(:namespace).as_null_object }
85
+ before { Wikilink::Converter::Namespace::Default.stub(:new) { default_namespace } }
86
+
87
+ shared_examples ''
88
+
89
+ context 'current site' do
90
+ let(:site_name) { CURRENT_SITE_NAME }
91
+ let(:converter) { Wikilink::Converter::Site.new name: site_name }
92
+
93
+ describe '#initialize' do
94
+ def initialize_site(&block)
95
+ Wikilink::Converter::Site.new name: site_name, &block
96
+ end
97
+
98
+ it 'sets option :prefix to "/"' do
99
+ converter.options[:prefix].should eq('/')
100
+ end
101
+ it 'sets option :external to false' do
102
+ converter.options[:external].should be_false
103
+ end
104
+ it 'sets up default namespace with option :site_name' do
105
+ klass = Wikilink::Converter::Namespace::Default
106
+ klass.should_receive(:new).with(hash_including(site_name: site_name))
107
+ initialize_site
108
+ end
109
+ it 'sets up default namespace with option :name' do
110
+ klass = Wikilink::Converter::Namespace::Default
111
+ klass.should_receive(:new).with(hash_including(name: DEFAULT_NAMESPACE))
112
+ initialize_site
113
+ end
114
+ it 'yields self' do
115
+ initialize_site do |arg|
116
+ arg.should be_a_kind_of(Wikilink::Converter::Site)
117
+ end
118
+ end
119
+
120
+ context 'with option :external true' do
121
+ let(:converter) { Wikilink::Converter::Site.new name: site_name, external: true }
122
+ it 'leaves option :external as true' do
123
+ converter.options[:external].should be_true
124
+ end
125
+ end
126
+ context 'with option :prefix "/wiki/"' do
127
+ let(:converter) { Wikilink::Converter::Site.new name: site_name, prefix: '/wiki/' }
128
+ it 'leaves option :prefix as "/wiki/"' do
129
+ converter.options[:prefix].should eq('/wiki/')
130
+ end
131
+ end
132
+ end
133
+
134
+ describe '#run' do
135
+ it 'delegates default namespace to Namespace::Default instance' do
136
+ ->{ converter.run(':', DEFAULT_NAMESPACE, 'Home', 'Name', '/') }.
137
+ should forward(:run).to(default_namespace).with(':', 'Home', 'Name', '/')
138
+ end
139
+ end
140
+
141
+ describe '#on_default_namespace' do
142
+ it 'is a shortcut of #on_namespace' do
143
+ converter.should_receive(:on_namespace).with(DEFAULT_NAMESPACE, 'arg')
144
+ converter.on_default_namespace 'arg'
145
+ end
146
+ end
147
+
148
+ describe '#on_namespace' do
149
+ context 'without any arguments nor block' do
150
+ let(:default_namespace) { double(:default_namespace) }
151
+
152
+ it 'does not change the default namespace handler' do
153
+ Wikilink::Converter::Namespace::Default.should_receive(:new).
154
+ once.and_return(default_namespace)
155
+ converter.on_namespace
156
+ end
157
+ end
158
+
159
+ context 'with block' do
160
+ it 'configures default namespace with the block' do
161
+ yielded = double('yielded')
162
+ yielded.should_receive(:poke)
163
+ default_namespace.should_receive(:config).and_yield
164
+ converter.on_namespace do
165
+ yielded.poke
166
+ end
167
+ end
168
+ end
169
+
170
+ context 'with options' do
171
+ let(:default_namespace) { double(:default_namespace) }
172
+
173
+ it 'does not change the default namespace handler' do
174
+ Wikilink::Converter::Namespace::Default.should_receive(:new).
175
+ once.and_return(default_namespace)
176
+ converter.on_namespace foo: :bar
177
+ end
178
+ end
179
+
180
+ context 'with default namespace name' do
181
+ let(:default_namespace) { double(:default_namespace) }
182
+
183
+ it 'does not change the default namespace handler' do
184
+ Wikilink::Converter::Namespace::Default.should_receive(:new).
185
+ once.and_return(default_namespace)
186
+ converter.on_namespace(DEFAULT_NAMESPACE)
187
+ end
188
+ end
189
+ context 'with other namespace name' do
190
+ let(:name) { 'topics' }
191
+ let(:klass) { Wikilink::Converter::Namespace }
192
+
193
+ it 'creates a new Wikilink::Converter::Namespace instance' do
194
+ klass.should_receive(:new)
195
+ converter.on_namespace name
196
+ end
197
+ it 'initializes Wikilink::Converter::Namespace instance with option :site_name' do
198
+ klass.should_receive(:new).with(hash_including(site_name: site_name))
199
+ converter.on_namespace name
200
+ end
201
+ it 'initializes Wikilink::Converter::Namespace instance with option :name' do
202
+ klass.should_receive(:new).with(hash_including(name: name))
203
+ converter.on_namespace name
204
+ end
205
+ it 'uses the instance of Wikilink::Converter::Namespace as new namespace converter' do
206
+ klass.should_receive(:new).and_return(namespace)
207
+ converter.on_namespace name
208
+ namespace.should_receive(:run).and_return('it works')
209
+ converter.run(':', name, 'Home', 'Name', '/').should eq('it works')
210
+ end
211
+
212
+ context 'with object' do
213
+ it 'uses that object as new namespace converter' do
214
+ converter.on_namespace name, namespace
215
+ namespace.should_receive(:run).and_return('it works')
216
+ converter.run(':', name, 'Home', 'Name', '/').should eq('it works')
217
+ end
218
+ end
219
+
220
+ it_behaves_like 'configuring a new instance of class as namespace handler', 'topics'
221
+ end
222
+
223
+ it_behaves_like 'configuring a new instance of class as namespace handler'
224
+
225
+ context 'with object' do
226
+ it 'uses that object as new namespace converter' do
227
+ converter.on_namespace namespace
228
+ namespace.should_receive(:run).and_return('it works')
229
+ converter.run(':', DEFAULT_NAMESPACE, 'Home', 'Name', '/').should eq('it works')
230
+ end
231
+ end
232
+
233
+ context 'with namespace, classname and options' do
234
+ end
235
+ end
236
+ end
237
+
238
+ context 'external site' do
239
+ let(:name) { 'wikipedia' }
240
+ let(:converter) { Wikilink::Converter::Site.new name: name }
241
+
242
+ describe '#initialize' do
243
+ alias_method :initialize_site, :converter
244
+
245
+ it 'does not set option :prefix' do
246
+ converter.options[:prefix].should be_nil
247
+ end
248
+ it 'sets option :external to true' do
249
+ converter.options[:external].should be_true
250
+ end
251
+
252
+ it 'sets up default namespace with option :site_name' do
253
+ klass = Wikilink::Converter::Namespace::Default
254
+ klass.should_receive(:new).with(hash_including(site_name: name))
255
+ initialize_site
256
+ end
257
+ it 'sets up default namespace with option :name' do
258
+ klass = Wikilink::Converter::Namespace::Default
259
+ klass.should_receive(:new).with(hash_including(name: DEFAULT_NAMESPACE))
260
+ initialize_site
261
+ end
262
+
263
+ context 'with option :external false' do
264
+ let(:converter) { Wikilink::Converter::Site.new name: name, external: false }
265
+ it 'leaves option :external as false' do
266
+ converter.options[:external].should be_false
267
+ end
268
+ end
269
+ context 'with option :prefix "/wiki/"' do
270
+ let(:converter) { Wikilink::Converter::Site.new name: name, prefix: '/wiki/' }
271
+ it 'leaves option :prefix as "/wiki/"' do
272
+ converter.options[:prefix].should eq('/wiki/')
273
+ end
274
+ end
275
+ end
276
+
277
+ describe '#run' do
278
+ it 'delegates default namespace to Namespace::Default instance' do
279
+ ->{ converter.run(':', DEFAULT_NAMESPACE, 'Home', 'Name', '/') }.
280
+ should forward(:run).to(default_namespace).with(':', 'Home', 'Name', '/')
281
+ end
282
+
283
+ context 'with method #on_namespace_topics defined' do
284
+ before { Wikilink::Converter::Namespace::Default.unstub(:new) }
285
+ class SpecSite < Wikilink::Converter::Site
286
+ def on_namespace_topics(colon, path, name, current_page)
287
+ 'it works'
288
+ end
289
+ end
290
+ let(:converter) { SpecSite.new }
291
+ it 'invokes #on_namespace_topics to handle namespace topics' do
292
+ converter.run(':', 'topics', 'Home', 'Name', '/').should eq('it works')
293
+ end
294
+
295
+ context 'but user has override it' do
296
+ before {
297
+ converter.namespace('topics') do
298
+ 'use this version'
299
+ end
300
+ }
301
+
302
+ it 'uses user version' do
303
+ converter.run(':', 'topics', 'Home', 'Name', '/').should eq('use this version')
304
+ end
305
+ end
306
+ end
307
+
308
+ context 'with method #on_namespace_ defined' do
309
+ before { Wikilink::Converter::Namespace::Default.unstub(:new) }
310
+ class SpecSite < Wikilink::Converter::Site
311
+ def on_namespace_(colon, path, name, current_page)
312
+ 'it works'
313
+ end
314
+ end
315
+ let(:converter) { SpecSite.new }
316
+ it 'invokes #on_namespace_ to handle default namespace' do
317
+ converter.run(':', DEFAULT_NAMESPACE, 'Home', 'Name', '/').should eq('it works')
318
+ end
319
+
320
+ context 'but user has override it' do
321
+ before {
322
+ converter.namespace do
323
+ 'use this version'
324
+ end
325
+ }
326
+
327
+ it 'uses user version' do
328
+ converter.run(':', DEFAULT_NAMESPACE, 'Home', 'Name', '/').should eq('use this version')
329
+ end
330
+ end
331
+ end
332
+ end
333
+ end
334
+ end
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.expand_path('../../../../spec_helper', __FILE__)
3
+ require 'wikilink/converter/sites/ruby_china'
4
+
5
+ describe Wikilink::Converter::Sites::RubyChina do
6
+ subject { converter.method(:run) }
7
+
8
+ context 'ruby-china.org' do
9
+ let(:rubychina) { Wikilink::Converter::Sites::RubyChina }
10
+ let(:converter) {
11
+ Wikilink::Converter.new { |on| on.current_site(rubychina) }
12
+ }
13
+
14
+ it { should convert('[[Ruby]]').to('<a href="/wiki/Ruby">Ruby</a>') }
15
+ it { should convert('[[topic:1]]').to('<a href="/topics/1">topic:1</a>') }
16
+ it { should convert('[[node:1]]').to('<a href="/topics/node1">node:1</a>') }
17
+ end
18
+
19
+ context 'external ruby-taiwan.org' do
20
+ let(:rubytaiwan) { Wikilink::Converter::Sites::RubyTaiwan }
21
+ let(:converter) {
22
+ Wikilink::Converter.new { |on|
23
+ on.site('rubytaiwan', rubytaiwan)
24
+ }
25
+ }
26
+
27
+ it { should convert('[[rubytaiwan:Ruby]]').to('<a class="external" href="http://ruby-taiwan.org/wiki/Ruby">rubytaiwan:Ruby</a>') }
28
+ it { should convert('[[rubytaiwan:topic:1]]').to('<a class="external" href="http://ruby-taiwan.org/topics/1">rubytaiwan:topic:1</a>') }
29
+ it { should convert('[[rubytaiwan:node:1]]').to('<a class="external" href="http://ruby-taiwan.org/topics/node1">rubytaiwan:node:1</a>') }
30
+ end
31
+ end
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.expand_path('../../../../spec_helper', __FILE__)
3
+ require 'wikilink/converter/sites/wikipedia'
4
+
5
+ describe Wikilink::Converter::Sites::Wikipedia do
6
+ subject { converter.method(:run) }
7
+
8
+ context 'en current site' do
9
+ let(:wikipedia) { Wikilink::Converter::Sites::Wikipedia }
10
+ let(:converter) {
11
+ Wikilink::Converter.new { |on| on.current_site(wikipedia) }
12
+ }
13
+ it { should convert('[[Ruby]]').to('<a href="/wiki/Ruby">Ruby</a>')}
14
+ end
15
+
16
+ context 'zh external site' do
17
+ let(:wikipedia) { Wikilink::Converter::Sites::Wikipedia }
18
+ let(:converter) {
19
+ Wikilink::Converter.new(lang: 'zh') do |on|
20
+ on.site('wiki', wikipedia)
21
+ end
22
+ }
23
+ it { should convert('[[wiki:红宝石]]').to('<a class="external" href="http://zh.wikipedia.org/wiki/红宝石">wiki:红宝石</a>')}
24
+ end
25
+ end