rdoc-sinatra 1

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,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ # Autotest.add_hook :initialize do |at|
6
+ # at.extra_files << "../some/external/dependency.rb"
7
+ #
8
+ # at.libs << ":../some/external"
9
+ #
10
+ # at.add_exception 'vendor'
11
+ #
12
+ # at.add_mapping(/dependency.rb/) do |f, _|
13
+ # at.files_matching(/test_.*rb$/)
14
+ # end
15
+ #
16
+ # %w(TestA TestB).each do |klass|
17
+ # at.extra_class_map[klass] = "test/test_misc.rb"
18
+ # end
19
+ # end
20
+
21
+ # Autotest.add_hook :run_command do |at|
22
+ # system "rake build"
23
+ # end
File without changes
@@ -0,0 +1,12 @@
1
+ *.rbc
2
+ doc/
3
+ /doc
4
+ pkg/
5
+ /pkg
6
+ coverage/
7
+ .yardoc/
8
+ /tags
9
+ TAGS
10
+ *.gem
11
+ .bundle
12
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rdoc-sinatra.gemspec
4
+ gemspec
@@ -0,0 +1,83 @@
1
+ rdoc-sinatra
2
+ ============
3
+
4
+ RDoc plugin for documenting Sinatra applications.
5
+
6
+
7
+ Homepage and Bugtracker
8
+ -----------------------
9
+
10
+ https://github.com/rdoc/rdoc-sinatra
11
+
12
+
13
+ Requirements
14
+ ------------
15
+
16
+ - rdoc 3+
17
+
18
+
19
+ Installation
20
+ ------------
21
+
22
+ `$ gem install rdoc-rake`
23
+
24
+
25
+ Usage
26
+ -----
27
+
28
+ `$ rdoc FILE_OR_DIR […]`
29
+
30
+ The plugin extracts documentation for route definitions marked with
31
+ a double-hash (that bit is important):
32
+
33
+ ##
34
+ # This is your documentation.
35
+ #
36
+ # And then some.
37
+ #
38
+ get "/foo" do
39
+ :yay
40
+ end
41
+
42
+ This plugin augments the normal RDoc Ruby parser, so that you can
43
+ generate the documentation along with the rest of your methods.
44
+
45
+ The route docs are placed under a fake class called Application Routes.
46
+
47
+
48
+ Limitations/TODO
49
+ ----------------
50
+
51
+ - Currently all routes are parsed into the top-level Application Routes.
52
+ This'll probably change in the next version.
53
+ - Does not actually parse the route patterns, so parameters and so
54
+ on aren't documented separately (you'll just see the entire pattern).
55
+
56
+
57
+
58
+ Licence
59
+ -------
60
+
61
+ (The MIT License)
62
+
63
+ Copyright (c) 2011 Eero Saynatkari
64
+
65
+ Permission is hereby granted, free of charge, to any person obtaining
66
+ a copy of this software and associated documentation files (the
67
+ 'Software'), to deal in the Software without restriction, including
68
+ without limitation the rights to use, copy, modify, merge, publish,
69
+ distribute, sublicense, and/or sell copies of the Software, and to
70
+ permit persons to whom the Software is furnished to do so, subject to
71
+ the following conditions:
72
+
73
+ The above copyright notice and this permission notice shall be
74
+ included in all copies or substantial portions of the Software.
75
+
76
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
77
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
78
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
79
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
80
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
81
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
82
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
83
+
@@ -0,0 +1,14 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require "rubygems"
4
+ require "bundler/gem_tasks"
5
+
6
+ require "rake/testtask"
7
+
8
+
9
+ Rake::TestTask.new do |t|
10
+ t.libs.push "lib"
11
+ t.test_files = FileList["test/test_*.rb"]
12
+ t.verbose = true
13
+ end
14
+
@@ -0,0 +1,7 @@
1
+ begin
2
+ gem "rdoc", "~> 3"
3
+ require "rdoc/parser/sinatra"
4
+
5
+ rescue Gem::LoadError
6
+ # Meh
7
+ end
@@ -0,0 +1,145 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require "rdoc"
4
+ require "rdoc/parser/ruby"
5
+
6
+
7
+ #
8
+ # Artificial scope for top-level routes.
9
+ #
10
+ class RDoc::SinatraRoutes < RDoc::AnonClass
11
+ end
12
+
13
+ #
14
+ # Sinatra route definition as a method.
15
+ #
16
+ class RDoc::SinatraRoute < RDoc::AnyMethod
17
+
18
+ def initialize(route_definition, content_text)
19
+ super(content_text, route_definition)
20
+
21
+ @params = ""
22
+ end
23
+
24
+ def aref_prefix
25
+ ""
26
+ end
27
+ end
28
+
29
+ #
30
+ # Sinatra routing error definition as a method.
31
+ #
32
+ class RDoc::SinatraRouteError < RDoc::SinatraRoute
33
+ end
34
+
35
+
36
+ #
37
+ # An augmented Ruby parser for Sinatra projects.
38
+ #
39
+ # In addition to normal Ruby doc, documentation is also extracted
40
+ # for route definitions.
41
+ #
42
+ class RDoc::Parser::Sinatra < RDoc::Parser::Ruby
43
+
44
+ # Re-declare to force overriding the normal .rb handler.
45
+ parse_files_matching /\.rbw?$/i
46
+
47
+
48
+ HTTP_VERBS = %w[GET HEAD POST PUT PATCH DELETE OPTIONS]
49
+ HTTP_ERRORS = {"NOT_FOUND" => 404, "ERROR" => 500}
50
+
51
+
52
+ #
53
+ # New parser, adds a top-level Application Routes.
54
+ #
55
+ def initialize(top_level, file_name, content, options, stats)
56
+ super
57
+
58
+ # Tuck away our little special module
59
+ @routes = @top_level.add_module RDoc::SinatraRoutes, "Application Routes"
60
+
61
+ @current_route = nil
62
+ end
63
+
64
+ #
65
+ # Override normal meta-method parsing to handle Sinatra routes and errors.
66
+ #
67
+ def parse_meta_method(container, single, token, comment)
68
+ name = token.name.upcase
69
+
70
+ case name
71
+ when *HTTP_VERBS
72
+ r = parse_route_definition token
73
+ r.comment = comment
74
+ when "NOT_FOUND", "ERROR"
75
+ r = parse_error_definition token
76
+ r.comment = comment
77
+ else
78
+ super
79
+ end
80
+ end
81
+
82
+
83
+ private
84
+
85
+ def parse_route_definition(http_method_token)
86
+ start_collecting_tokens
87
+ add_token http_method_token
88
+
89
+ token_listener(self) {
90
+ skip_tkspace false
91
+
92
+ pattern_token = get_tk
93
+ route_pattern = pattern_token.text
94
+
95
+ route_name = "#{http_method_token.name.upcase} #{route_pattern}"
96
+
97
+ if r = @routes.find_instance_method_named(route_name)
98
+ warn "Redefining route #{route_name}"
99
+ @current_route = r
100
+ else
101
+ @current_route = RDoc::SinatraRoute.new route_name, tokens_to_s
102
+ @routes.add_method @current_route
103
+ @stats.add_method @current_route
104
+ end
105
+ }
106
+
107
+ @current_route
108
+ end
109
+
110
+ def parse_error_definition(error_token)
111
+ start_collecting_tokens
112
+ add_token error_token
113
+
114
+ token_listener(self) {
115
+ skip_tkspace false
116
+
117
+ pattern_token = get_tk
118
+
119
+ status_codes = if TkDO === pattern_token
120
+ HTTP_ERRORS["ERROR"]
121
+ else
122
+ pattern_token.text
123
+ end
124
+
125
+ if error_token.name == "not_found"
126
+ route_name = "error #{HTTP_ERRORS["NOT_FOUND"]}"
127
+ else
128
+ route_name = "error #{status_codes}"
129
+ end
130
+
131
+ if r = @routes.find_instance_method_named(route_name)
132
+ warn "Redefining error #{error_token.name} #{pattern_token}"
133
+ @current_route = r
134
+ else
135
+ @current_route = RDoc::SinatraRouteError.new route_name, tokens_to_s
136
+ @routes.add_method @current_route
137
+ @stats.add_method @current_route
138
+ end
139
+ }
140
+
141
+ @current_route
142
+ end
143
+
144
+
145
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "rdoc-sinatra"
5
+ s.version = `git tag -l | wc -l`.chomp.to_i
6
+
7
+ s.platform = Gem::Platform::RUBY
8
+
9
+ s.authors = ["Eero Saynatkari"]
10
+ s.email = ["projects@kittensoft.org"]
11
+ s.homepage = "http://github.com/rdoc/rdoc-sinatra"
12
+
13
+ s.summary = %q{RDoc for Sinatra routes.}
14
+ s.description = %q{RDoc plugin for extracting documentation for your Sinatra app's routes.}
15
+
16
+ s.files = `git ls-files`.split "\n"
17
+ s.test_files = `git ls-files -- test/*`.split "\n"
18
+
19
+ s.require_paths = %w{lib}
20
+
21
+ s.add_runtime_dependency "rdoc", "~> 3.0"
22
+
23
+ s.add_development_dependency "minitest"
24
+ end
25
+
@@ -0,0 +1,416 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require "stringio"
4
+ require "tempfile"
5
+
6
+ require "rdoc"
7
+ require "rdoc/parser/sinatra"
8
+
9
+ require "minitest/autorun"
10
+
11
+
12
+ class TestRDocParserSinatra < MiniTest::Unit::TestCase
13
+
14
+ def setup
15
+ @tempfile = Tempfile.new self.class.name
16
+ @filename = @tempfile.path
17
+
18
+ RDoc::TopLevel.reset
19
+ @top_level = RDoc::TopLevel.new @filename
20
+
21
+ @options = RDoc::Options.new
22
+ @options.quiet = true
23
+ @stats = RDoc::Stats.new 0
24
+
25
+ @route_definitions = @routes = nil
26
+ end
27
+
28
+ def teardown
29
+ @tempfile.close
30
+ end
31
+
32
+
33
+
34
+ def test_routes_stored_in_top_level_application_routes_class_hiding_in_modules
35
+ app = <<-APP
36
+ require "sinatra"
37
+
38
+ ##
39
+ # Route 1
40
+ #
41
+ get "/foo" do
42
+ :hi
43
+ end
44
+ APP
45
+
46
+ make_a_parser_for app
47
+ @parser.scan
48
+
49
+ r = RDoc::TopLevel.find_module_named "Application Routes"
50
+ r.wont_be_nil
51
+
52
+ r.method_list.first.name.must_equal 'GET "/foo"'
53
+ end
54
+
55
+ def test_route_presented_as_http_method_and_route_pattern
56
+ app = <<-APP
57
+ require "sinatra"
58
+
59
+ ##
60
+ # Route 2
61
+ #
62
+ # Some more text goes here.
63
+ #
64
+ get "/foo" do
65
+ :hi
66
+ end
67
+ APP
68
+
69
+ make_a_parser_for app
70
+ extract_routes
71
+
72
+ r = @routes.first
73
+
74
+ r.name.must_equal 'GET "/foo"'
75
+ r.comment.text.must_equal "Route 2\n\nSome more text goes here."
76
+ end
77
+
78
+ def test_route_pattern_may_be_regexp
79
+ app = <<-APP
80
+ require "sinatra"
81
+
82
+ ##
83
+ # Route 3
84
+ #
85
+ get /foo/ do
86
+ :hi
87
+ end
88
+
89
+ ##
90
+ # Route 4
91
+ #
92
+ get %r{bar} do
93
+ :ho
94
+ end
95
+ APP
96
+
97
+ make_a_parser_for app
98
+ extract_routes
99
+
100
+ @routes.size.must_equal 2
101
+
102
+ r = @routes.first
103
+ r.name.must_equal 'GET /foo/'
104
+ r.comment.text.must_equal "Route 3"
105
+
106
+ r = @routes.last
107
+ r.name.must_equal 'GET %r{bar}'
108
+ r.comment.text.must_equal "Route 4"
109
+ end
110
+
111
+
112
+ %w[GET HEAD POST PUT PATCH DELETE OPTIONS].each {|http|
113
+ define_method("test_parses_#{http}_definition") {
114
+ make_a_parser_for define_all_the_things!
115
+ extract_routes
116
+
117
+ @routes.find {|r| r.name.include? http }.wont_be_nil
118
+ }
119
+ }
120
+
121
+ def test_parses_error_definitions_without_status_code_defaulting_to_500
122
+ app = <<-APP
123
+ require "sinatra"
124
+
125
+ ##
126
+ # Gettersy
127
+ #
128
+ get "foo" do
129
+ :hi
130
+ end
131
+
132
+ ##
133
+ # OMG ERROR
134
+ #
135
+ error do
136
+ :haha
137
+ end
138
+ APP
139
+
140
+ make_a_parser_for app
141
+ extract_routes
142
+
143
+ @routes.size.must_equal 2
144
+
145
+ r = @routes.last
146
+ r.name.must_equal "error 500"
147
+ end
148
+
149
+ def test_parses_error_definitions_with_status_codes
150
+ app = <<-APP
151
+ require "sinatra"
152
+
153
+ ##
154
+ # Getters
155
+ #
156
+ get "foo" do
157
+ :hi
158
+ end
159
+
160
+ ##
161
+ # Fourohthree
162
+ #
163
+ error 403 do
164
+ :haha
165
+ end
166
+ APP
167
+
168
+ make_a_parser_for app
169
+ extract_routes
170
+
171
+ @routes.size.must_equal 2
172
+
173
+ r = @routes.last
174
+ r.name.must_equal "error 403"
175
+ end
176
+
177
+ def test_parses_not_found_definition_into_a_404_error
178
+ app = <<-APP
179
+ require "sinatra"
180
+
181
+ ##
182
+ # Route 5
183
+ #
184
+ get "foo" do
185
+ :hi
186
+ end
187
+
188
+ ##
189
+ # Route 6
190
+ #
191
+ not_found do
192
+ :haha
193
+ end
194
+ APP
195
+
196
+ make_a_parser_for app
197
+ extract_routes
198
+
199
+ @routes.size.must_equal 2
200
+
201
+ r = @routes.last
202
+ r.name.must_equal "error 404"
203
+ end
204
+
205
+ def test_parses_same_route_pattern_with_different_methods_as_separate
206
+ app = <<-APP
207
+ require "sinatra"
208
+
209
+ ##
210
+ # Route 7
211
+ #
212
+ get "foo" do
213
+ :hi
214
+ end
215
+
216
+ ##
217
+ # Route 8
218
+ #
219
+ put "foo" do
220
+ :ho
221
+ end
222
+ APP
223
+
224
+ make_a_parser_for app
225
+ extract_routes
226
+
227
+ @routes.size.must_equal 2
228
+
229
+ r = @routes.first
230
+ r.name.must_equal 'GET "foo"'
231
+
232
+ r = @routes.last
233
+ r.name.must_equal 'PUT "foo"'
234
+ end
235
+
236
+ def test_parses_same_route_pattern_with_same_method_as_the_same_and_latter_overrides
237
+ app = <<-APP
238
+ require "sinatra"
239
+
240
+ ##
241
+ # Initial definition
242
+ #
243
+ get "foo" do
244
+ :hi
245
+ end
246
+
247
+ ##
248
+ # YAY OVERRIDE
249
+ #
250
+ get "foo" do
251
+ :ho
252
+ end
253
+ APP
254
+
255
+ make_a_parser_for app
256
+ extract_routes
257
+
258
+ @routes.size.must_equal 1
259
+
260
+ r = @routes.first
261
+ r.name.must_equal 'GET "foo"'
262
+ r.comment.text.must_equal "YAY OVERRIDE"
263
+ end
264
+
265
+ # May end up not doing this at all.
266
+ # def test_get_definitions_automatically_add_a_head_definition_with_same_comment
267
+ # flunk
268
+ # end
269
+
270
+ def test_allows_normal_ruby_docs_to_be_mixed_in_same_doc
271
+ app = <<-APP
272
+ require "sinatra"
273
+
274
+ ##
275
+ # Route def
276
+ #
277
+ get "foo" do
278
+ :hi
279
+ end
280
+
281
+ #
282
+ # Random method
283
+ #
284
+ def foo; end
285
+
286
+ #
287
+ # Random class
288
+ #
289
+ class Yay
290
+
291
+ ##
292
+ # Random metamethod
293
+ #
294
+ some_meta :metafoo
295
+
296
+ #
297
+ # Random method in a class
298
+ #
299
+ def yayfoo; end
300
+ end
301
+ APP
302
+
303
+ make_a_parser_for app
304
+ extract_routes
305
+
306
+ @routes.size.must_equal 1
307
+
308
+ o = RDoc::TopLevel.find_class_named "Object"
309
+ o.method_list.first.name.must_equal "foo"
310
+
311
+ y = RDoc::TopLevel.find_class_named "Yay"
312
+ y.method_list.size.must_equal 2
313
+
314
+ y.method_list.shift.name.must_equal "metafoo"
315
+ y.method_list.shift.name.must_equal "yayfoo"
316
+ end
317
+
318
+ def test_parses_route_inside_a_class_definition
319
+ app = <<-APP
320
+ require "sinatra"
321
+
322
+ class Yay < Sinatra::Base
323
+ ##
324
+ # Route 9
325
+ #
326
+ get "foo" do
327
+ :hi
328
+ end
329
+ end
330
+ APP
331
+
332
+ make_a_parser_for app
333
+ extract_routes
334
+
335
+ @routes.size.must_equal 1
336
+
337
+ r = @routes.first
338
+ r.name.must_equal 'GET "foo"'
339
+ end
340
+
341
+ # def test_parses_route_inside_a_sinatra_base_inheriting_class_only
342
+ # flunk
343
+ # end
344
+ #
345
+ # def test_parses_route_inside_a_base_class_into_that_class_not_application_routes
346
+ # flunk
347
+ # end
348
+
349
+
350
+ private
351
+
352
+ def make_a_parser_for(content)
353
+ @parser = RDoc::Parser::Sinatra.new @top_level, @filename, content, @options, @stats
354
+ end
355
+
356
+ def extract_routes
357
+ @parser.scan
358
+ @route_definitions = RDoc::TopLevel.find_module_named "Application Routes"
359
+ @routes = @route_definitions.method_list
360
+ end
361
+
362
+ def define_all_the_things!
363
+ <<-END
364
+ require "sinatra"
365
+
366
+ ##
367
+ # GET route
368
+ #
369
+ get "/foo" do
370
+ "hi"
371
+ end
372
+
373
+ ##
374
+ # HEAD route
375
+ #
376
+ head "/bar" do
377
+ "ho"
378
+ end
379
+
380
+ ##
381
+ # POST route
382
+ #
383
+ post "/foo/:id" do
384
+ :yay
385
+ end
386
+
387
+ ##
388
+ # PUT route
389
+ #
390
+ put "/foo/:id" do
391
+ :yay
392
+ end
393
+
394
+ ##
395
+ # DELETE route
396
+ #
397
+ delete %r{hi there} do
398
+ :ugg
399
+ end
400
+
401
+ ##
402
+ # PATCH route
403
+ #
404
+ patch /foo^bar/ do
405
+ :mug
406
+ end
407
+
408
+ ##
409
+ # OPTIONS route
410
+ #
411
+ options "foo/" do
412
+ :whatevs
413
+ end
414
+ END
415
+ end
416
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rdoc-sinatra
3
+ version: !ruby/object:Gem::Version
4
+ version: '1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Eero Saynatkari
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rdoc
16
+ requirement: &70238704092380 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70238704092380
25
+ - !ruby/object:Gem::Dependency
26
+ name: minitest
27
+ requirement: &70238704091140 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70238704091140
36
+ description: RDoc plugin for extracting documentation for your Sinatra app's routes.
37
+ email:
38
+ - projects@kittensoft.org
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - .autotest
44
+ - .gemtest
45
+ - .gitignore
46
+ - Gemfile
47
+ - README.md
48
+ - Rakefile
49
+ - lib/rdoc/discover.rb
50
+ - lib/rdoc/parser/sinatra.rb
51
+ - rdoc-sinatra.gemspec
52
+ - test/test_rdoc_parser_sinatra.rb
53
+ homepage: http://github.com/rdoc/rdoc-sinatra
54
+ licenses: []
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubyforge_project:
73
+ rubygems_version: 1.8.10
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: RDoc for Sinatra routes.
77
+ test_files:
78
+ - test/test_rdoc_parser_sinatra.rb