sinatra-croon 0.0.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.
- data/README.md +43 -0
- data/Rakefile +58 -0
- data/lib/sinatra/croon/views/docs.haml +41 -0
- data/lib/sinatra/croon/views/docs.sass +106 -0
- data/lib/sinatra/croon.rb +108 -0
- data/spec/sinatra/croon_spec.rb +84 -0
- data/spec/spec_helper.rb +11 -0
- metadata +170 -0
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Sinatra::Croon
|
2
|
+
|
3
|
+
Allows you to add inline documentation to a Sinatra app and have a web-based
|
4
|
+
documentation browser be available to you.
|
5
|
+
|
6
|
+
## Usage
|
7
|
+
|
8
|
+
require "sinatra/croon"
|
9
|
+
|
10
|
+
class MyApp < Sinatra::Base
|
11
|
+
register Sinatra::Croon
|
12
|
+
end
|
13
|
+
|
14
|
+
## Documentation Format
|
15
|
+
|
16
|
+
# Create an application.
|
17
|
+
#
|
18
|
+
# @param <name> the name of the application to create
|
19
|
+
# @param [stack] the stack on which to create the application
|
20
|
+
#
|
21
|
+
# @request
|
22
|
+
# POST /apps.json
|
23
|
+
# name=example&stack=bamboo-ree-1.8.7
|
24
|
+
# @response
|
25
|
+
# {
|
26
|
+
# "id": 1,
|
27
|
+
# "name": "example",
|
28
|
+
# "owner": "user@example.org",
|
29
|
+
# "created_at": "Sat Jan 01 00:00:00 UTC 2000",
|
30
|
+
# "stack": "bamboo-ree-1.8.7",
|
31
|
+
# "slug_size": 1000000,
|
32
|
+
# "repo_size": 500000,
|
33
|
+
# "dynos": 1,
|
34
|
+
# "workers": 0
|
35
|
+
# }
|
36
|
+
|
37
|
+
post "/apps.json" do
|
38
|
+
# do something here
|
39
|
+
end
|
40
|
+
|
41
|
+
## Web-based browser
|
42
|
+
|
43
|
+
Sinatra::Croon will create a route at `/docs` to display your documentation.
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake"
|
3
|
+
require "rspec"
|
4
|
+
require "rspec/core/rake_task"
|
5
|
+
|
6
|
+
$:.unshift File.expand_path("../lib", __FILE__)
|
7
|
+
require "sinatra/croon"
|
8
|
+
|
9
|
+
task :default => :spec
|
10
|
+
|
11
|
+
desc "Run all specs"
|
12
|
+
Rspec::Core::RakeTask.new(:spec) do |t|
|
13
|
+
t.pattern = 'spec/**/*_spec.rb'
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Generate RCov code coverage report"
|
17
|
+
task :rcov => "rcov:build" do
|
18
|
+
%x{ open coverage/index.html }
|
19
|
+
end
|
20
|
+
|
21
|
+
Rspec::Core::RakeTask.new("rcov:build") do |t|
|
22
|
+
t.pattern = 'spec/**/*_spec.rb'
|
23
|
+
t.rcov = true
|
24
|
+
t.rcov_opts = [ "--exclude", Gem.default_dir, "--exclude", "spec" ]
|
25
|
+
end
|
26
|
+
|
27
|
+
######################################################
|
28
|
+
|
29
|
+
begin
|
30
|
+
require 'jeweler'
|
31
|
+
Jeweler::Tasks.new do |s|
|
32
|
+
s.name = "sinatra-croon"
|
33
|
+
s.version = Sinatra::Croon::VERSION
|
34
|
+
|
35
|
+
s.summary = "Create documentation for an API built in Sinatra."
|
36
|
+
s.description = s.summary
|
37
|
+
s.author = "David Dollar"
|
38
|
+
s.email = "ddollar@gmail.com"
|
39
|
+
s.homepage = "http://daviddollar.org/"
|
40
|
+
|
41
|
+
s.platform = Gem::Platform::RUBY
|
42
|
+
s.has_rdoc = false
|
43
|
+
|
44
|
+
s.files = %w(Rakefile README.markdown) + Dir["{lib,spec}/**/*"]
|
45
|
+
s.require_path = "lib"
|
46
|
+
|
47
|
+
s.add_development_dependency 'rack-test', '~> 0.5.4'
|
48
|
+
s.add_development_dependency 'rake', '~> 0.8.7'
|
49
|
+
s.add_development_dependency 'rspec', '~> 2.0.0.beta.5'
|
50
|
+
s.add_development_dependency 'webrat', '~> 0.7.1'
|
51
|
+
|
52
|
+
s.add_dependency 'haml', '~> 3.0.12'
|
53
|
+
s.add_dependency 'sinatra', '~> 1.0'
|
54
|
+
end
|
55
|
+
Jeweler::GemcutterTasks.new
|
56
|
+
rescue LoadError
|
57
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler"
|
58
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
!!! 5
|
2
|
+
|
3
|
+
%html
|
4
|
+
|
5
|
+
%head
|
6
|
+
%title API Documentation
|
7
|
+
%link{ :rel => "stylesheet", :href => "/docs.css" }
|
8
|
+
|
9
|
+
%body
|
10
|
+
|
11
|
+
#content
|
12
|
+
|
13
|
+
%h1
|
14
|
+
%a{ :href => '/' } API Documentation
|
15
|
+
|
16
|
+
- docs.each do |doc|
|
17
|
+
|
18
|
+
.api
|
19
|
+
|
20
|
+
.url
|
21
|
+
%a
|
22
|
+
= doc[:verb].upcase
|
23
|
+
= doc[:uri]
|
24
|
+
|
25
|
+
.description
|
26
|
+
= doc[:description]
|
27
|
+
|
28
|
+
- if (doc[:params] || []).length > 0
|
29
|
+
.params
|
30
|
+
- doc[:params].each do |param|
|
31
|
+
.param
|
32
|
+
.type{ :class => (param[:required] && "required") }
|
33
|
+
= (param[:required]) ? "REQUIRED" : "OPTIONAL"
|
34
|
+
.name= escape_html(param[:name])
|
35
|
+
.description= param[:description]
|
36
|
+
|
37
|
+
%code.request
|
38
|
+
= display_code doc[:request]
|
39
|
+
|
40
|
+
%code.response
|
41
|
+
= display_code doc[:response]
|
@@ -0,0 +1,106 @@
|
|
1
|
+
*
|
2
|
+
:font-family Helvetica, Arial, sans-serif
|
3
|
+
|
4
|
+
=code_title
|
5
|
+
:display block
|
6
|
+
:padding 6px 10px
|
7
|
+
:font-weight bold
|
8
|
+
:background #ccc
|
9
|
+
:color #333
|
10
|
+
:margin-left -12px
|
11
|
+
:margin-right -12px
|
12
|
+
:margin-top -12px
|
13
|
+
:margin-bottom 12px
|
14
|
+
|
15
|
+
h2
|
16
|
+
:background #555
|
17
|
+
:color #fff
|
18
|
+
:border 1px #666 solid
|
19
|
+
:padding 10px
|
20
|
+
a
|
21
|
+
:color #fff
|
22
|
+
:text-decoration none
|
23
|
+
|
24
|
+
.api
|
25
|
+
:margin-bottom 24px
|
26
|
+
:background #eee
|
27
|
+
:border 1px #ccc solid
|
28
|
+
|
29
|
+
.url
|
30
|
+
:padding 6px 10px
|
31
|
+
:background #aaa
|
32
|
+
:border-bottom 1px #ccc solid
|
33
|
+
a
|
34
|
+
:color #333
|
35
|
+
:font-size 1.6em
|
36
|
+
:font-weight bold
|
37
|
+
:font-family monospace
|
38
|
+
|
39
|
+
.description
|
40
|
+
:padding 12px
|
41
|
+
|
42
|
+
code
|
43
|
+
:font-family Monaco, monospace
|
44
|
+
:white-space pre
|
45
|
+
:padding 12px
|
46
|
+
:display block
|
47
|
+
|
48
|
+
.params
|
49
|
+
:margin-bottom 10px
|
50
|
+
:padding 12px
|
51
|
+
:display block
|
52
|
+
&:before
|
53
|
+
+code_title
|
54
|
+
:content "Parameters"
|
55
|
+
.param
|
56
|
+
:line-height 30px
|
57
|
+
.name
|
58
|
+
:display inline
|
59
|
+
:font-weight bold
|
60
|
+
:font-family monospace
|
61
|
+
:font-size 1.2em
|
62
|
+
.type
|
63
|
+
:font-weight bold
|
64
|
+
:font-size 0.6em
|
65
|
+
:color #999
|
66
|
+
:display inline-block
|
67
|
+
:width 65px
|
68
|
+
.required
|
69
|
+
:color #333
|
70
|
+
.description
|
71
|
+
:display inline
|
72
|
+
|
73
|
+
.request
|
74
|
+
&:before
|
75
|
+
+code_title
|
76
|
+
:content "Request"
|
77
|
+
|
78
|
+
.response
|
79
|
+
&:before
|
80
|
+
+code_title
|
81
|
+
:content "Response"
|
82
|
+
|
83
|
+
body
|
84
|
+
:margin 0
|
85
|
+
|
86
|
+
#content
|
87
|
+
:width 800px
|
88
|
+
:margin-left auto
|
89
|
+
:margin-right auto
|
90
|
+
|
91
|
+
#index
|
92
|
+
.section
|
93
|
+
:margin-bottom 20px
|
94
|
+
.summarydoc
|
95
|
+
:border 1px #ccc solid
|
96
|
+
:padding 12px
|
97
|
+
:margin-top 10px
|
98
|
+
:background #eee
|
99
|
+
.path
|
100
|
+
:margin-bottom 10px
|
101
|
+
a
|
102
|
+
:font-family monospace
|
103
|
+
:font-weight bold
|
104
|
+
:font-size 1.4em
|
105
|
+
.description
|
106
|
+
:color #666
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require "haml"
|
2
|
+
require "sinatra/base"
|
3
|
+
|
4
|
+
module Sinatra
|
5
|
+
module Croon
|
6
|
+
VERSION = "0.0.1"
|
7
|
+
|
8
|
+
def self.registered(app)
|
9
|
+
app.helpers Croon::Helpers
|
10
|
+
@app = app
|
11
|
+
|
12
|
+
app.get '/docs.css' do
|
13
|
+
pass do
|
14
|
+
content_type "text/css"
|
15
|
+
template = File.read(File.expand_path("../croon/views/docs.sass", __FILE__))
|
16
|
+
sass template
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
app.get '/docs' do
|
21
|
+
pass do
|
22
|
+
template = File.read(File.expand_path("../croon/views/docs.haml", __FILE__))
|
23
|
+
haml template, :locals => { :docs => documentation }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.route_added(verb, path, block)
|
29
|
+
return if verb.to_s == "HEAD"
|
30
|
+
|
31
|
+
route_location = caller(1).reject { |line| line =~ /sinatra\/base/ }.first
|
32
|
+
file, line = route_location.split(':')
|
33
|
+
doc = Croon::Parser.parse_route_documentation(file, line.to_i)
|
34
|
+
|
35
|
+
if doc[:description]
|
36
|
+
doc[:verb] = verb
|
37
|
+
doc[:uri] = path
|
38
|
+
@app.documentation << doc
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def documentation
|
43
|
+
@documentation ||= []
|
44
|
+
end
|
45
|
+
|
46
|
+
module Helpers
|
47
|
+
def display_code(code)
|
48
|
+
Haml::Filters::Preserve.render(Haml::Filters::Escaped.render(code))
|
49
|
+
end
|
50
|
+
|
51
|
+
def documentation
|
52
|
+
self.class.documentation
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
module Parser
|
57
|
+
def self.parse_route_documentation(filename, line)
|
58
|
+
all_lines = File.read(filename).split("\n").reverse
|
59
|
+
index_start = all_lines.length - line + 1
|
60
|
+
num_lines = all_lines[index_start..-1].index { |l| !['', '#'].include?(l.strip[0..0]) }
|
61
|
+
doc_lines = all_lines[index_start, num_lines].reverse
|
62
|
+
|
63
|
+
parse_comments(doc_lines)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.parse_comments(comments)
|
67
|
+
key = :description
|
68
|
+
|
69
|
+
comments.inject({}) do |parsed, comment|
|
70
|
+
case comment.strip
|
71
|
+
when /\A#\s*@param\s+(.+?)\s+(.+)/ then
|
72
|
+
parsed[:params] ||= []
|
73
|
+
required = $1[0..0] == '<'
|
74
|
+
name = $1[1..-2]
|
75
|
+
parsed[:params] << { :name => name, :description => $2, :required => required }
|
76
|
+
when /\A#\s*@(\w+)\s*(.*)\Z/ then
|
77
|
+
key = $1.to_sym
|
78
|
+
parsed[key] ||= []
|
79
|
+
parsed[key] << $2 if $2
|
80
|
+
when /\A#(.+)\Z/ then
|
81
|
+
parsed[key] ||= []
|
82
|
+
parsed[key] << $1
|
83
|
+
end
|
84
|
+
parsed
|
85
|
+
end.inject({}) do |flattened, (k, v)|
|
86
|
+
case v.first
|
87
|
+
when String then
|
88
|
+
flattened[k] = strip_left(v.reject { |l| l.strip == "" }.join("\n"))
|
89
|
+
else
|
90
|
+
flattened[k] = v
|
91
|
+
end
|
92
|
+
flattened
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.strip_left(code)
|
97
|
+
first_line = code.split("\n").first
|
98
|
+
return code unless first_line
|
99
|
+
num_spaces = first_line.match(/\A */)[0].length
|
100
|
+
code.split("\n").map do |line|
|
101
|
+
line[num_spaces..-1]
|
102
|
+
end.join("\n")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
register Croon
|
108
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "sinatra/base"
|
3
|
+
require "sinatra/croon"
|
4
|
+
|
5
|
+
class MockSinatraApp < Sinatra::Base
|
6
|
+
register Sinatra::Croon
|
7
|
+
|
8
|
+
# Show an application.
|
9
|
+
#
|
10
|
+
# @request GET /apps.json
|
11
|
+
# @response { "status" : "ok" }
|
12
|
+
|
13
|
+
get "/apps.json" do
|
14
|
+
# do something here
|
15
|
+
end
|
16
|
+
|
17
|
+
# Create an application.
|
18
|
+
#
|
19
|
+
# @param <name> the name of the application to create
|
20
|
+
# @param [stack] the stack on which to create the application
|
21
|
+
#
|
22
|
+
# @request
|
23
|
+
# POST /apps.json
|
24
|
+
# name=example&stack=bamboo-ree-1.8.7
|
25
|
+
#
|
26
|
+
# @response
|
27
|
+
# {
|
28
|
+
# "id": 1,
|
29
|
+
# "name": "example",
|
30
|
+
# "owner": "user@example.org",
|
31
|
+
# "created_at": "Sat Jan 01 00:00:00 UTC 2000",
|
32
|
+
# "stack": "bamboo-ree-1.8.7",
|
33
|
+
# "slug_size": 1000000,
|
34
|
+
# "repo_size": 500000,
|
35
|
+
# "dynos": 1,
|
36
|
+
# "workers": 0
|
37
|
+
# }
|
38
|
+
|
39
|
+
post "/apps.json" do
|
40
|
+
# do something here
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe Sinatra::Croon do
|
45
|
+
include Rack::Test::Methods
|
46
|
+
include Webrat::Matchers
|
47
|
+
|
48
|
+
let(:app) { MockSinatraApp.new }
|
49
|
+
|
50
|
+
it "can set a description" do
|
51
|
+
get "/docs"
|
52
|
+
last_response.should have_selector(".description", :content => "Show an application.")
|
53
|
+
last_response.should have_selector(".description", :content => "Create an application.")
|
54
|
+
end
|
55
|
+
|
56
|
+
it "can set params" do
|
57
|
+
get "/docs"
|
58
|
+
last_response.should have_selector(".param") do |param|
|
59
|
+
param.should have_selector(".type.required")
|
60
|
+
param.should have_selector(".name", :content => "name")
|
61
|
+
param.should have_selector(".description", :content => "the name of the application to create")
|
62
|
+
end
|
63
|
+
last_response.should have_selector(".param") do |param|
|
64
|
+
param.should have_selector(".name", :content => "stack")
|
65
|
+
param.should have_selector(".description", :content => "the stack on which to create the application")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "can set a request" do
|
70
|
+
get "/docs"
|
71
|
+
last_response.should have_selector(".request", :content => "GET /apps.json")
|
72
|
+
end
|
73
|
+
|
74
|
+
it "can set a response" do
|
75
|
+
get "/docs"
|
76
|
+
last_response.should have_selector(".response", :content => '{ "status" : "ok" }')
|
77
|
+
end
|
78
|
+
|
79
|
+
it "has a default style" do
|
80
|
+
get "/docs.css"
|
81
|
+
last_response.should =~ /\.response/
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sinatra-croon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- David Dollar
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-21 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rack-test
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 5
|
33
|
+
- 4
|
34
|
+
version: 0.5.4
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rake
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 49
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
- 8
|
49
|
+
- 7
|
50
|
+
version: 0.8.7
|
51
|
+
type: :development
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: rspec
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 62196457
|
62
|
+
segments:
|
63
|
+
- 2
|
64
|
+
- 0
|
65
|
+
- 0
|
66
|
+
- beta
|
67
|
+
- 5
|
68
|
+
version: 2.0.0.beta.5
|
69
|
+
type: :development
|
70
|
+
version_requirements: *id003
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: webrat
|
73
|
+
prerelease: false
|
74
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ~>
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 1
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
- 7
|
83
|
+
- 1
|
84
|
+
version: 0.7.1
|
85
|
+
type: :development
|
86
|
+
version_requirements: *id004
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
name: haml
|
89
|
+
prerelease: false
|
90
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ~>
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
hash: 31
|
96
|
+
segments:
|
97
|
+
- 3
|
98
|
+
- 0
|
99
|
+
- 12
|
100
|
+
version: 3.0.12
|
101
|
+
type: :runtime
|
102
|
+
version_requirements: *id005
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: sinatra
|
105
|
+
prerelease: false
|
106
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ~>
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
hash: 15
|
112
|
+
segments:
|
113
|
+
- 1
|
114
|
+
- 0
|
115
|
+
version: "1.0"
|
116
|
+
type: :runtime
|
117
|
+
version_requirements: *id006
|
118
|
+
description: Create documentation for an API built in Sinatra.
|
119
|
+
email: ddollar@gmail.com
|
120
|
+
executables: []
|
121
|
+
|
122
|
+
extensions: []
|
123
|
+
|
124
|
+
extra_rdoc_files:
|
125
|
+
- README.md
|
126
|
+
files:
|
127
|
+
- Rakefile
|
128
|
+
- lib/sinatra/croon.rb
|
129
|
+
- lib/sinatra/croon/views/docs.haml
|
130
|
+
- lib/sinatra/croon/views/docs.sass
|
131
|
+
- spec/sinatra/croon_spec.rb
|
132
|
+
- spec/spec_helper.rb
|
133
|
+
- README.md
|
134
|
+
has_rdoc: true
|
135
|
+
homepage: http://daviddollar.org/
|
136
|
+
licenses: []
|
137
|
+
|
138
|
+
post_install_message:
|
139
|
+
rdoc_options:
|
140
|
+
- --charset=UTF-8
|
141
|
+
require_paths:
|
142
|
+
- lib
|
143
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
144
|
+
none: false
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
hash: 3
|
149
|
+
segments:
|
150
|
+
- 0
|
151
|
+
version: "0"
|
152
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ">="
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
hash: 3
|
158
|
+
segments:
|
159
|
+
- 0
|
160
|
+
version: "0"
|
161
|
+
requirements: []
|
162
|
+
|
163
|
+
rubyforge_project:
|
164
|
+
rubygems_version: 1.3.7
|
165
|
+
signing_key:
|
166
|
+
specification_version: 3
|
167
|
+
summary: Create documentation for an API built in Sinatra.
|
168
|
+
test_files:
|
169
|
+
- spec/sinatra/croon_spec.rb
|
170
|
+
- spec/spec_helper.rb
|