rack-usermanual 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +39 -0
- data/lib/rack/usermanual/app.rb +73 -0
- data/lib/rack/usermanual.rb +1 -0
- data/lib/rack-usermanual.rb +1 -0
- data/rack-usermanual.gemspec +27 -0
- data/spec/fixtures/features/my-section/test.feature +8 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/usermanual_spec.rb +39 -0
- data/views/_menu.haml +10 -0
- data/views/_pending.haml +4 -0
- data/views/index.haml +7 -0
- data/views/page.haml +45 -0
- metadata +161 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YTU5Mzg1NWM1NzFkMzA5Y2RiMDc2OWNhYjBlMzRjZjNjNmM1YzU0MQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MDE4NDA4NzI1MTcxNDM1Y2IxMTc0NmM2NTYwYjNkZjdkOTgyMTZhZA==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MjVmNDQ2ZmJmNDFlMGQ4NmVlYmRiZWUwYWY5MzA0N2IyNzhkYmYwNzU2OGU4
|
10
|
+
MTRhYzBlZDVlYTMwODIwMWUyYzVjYTBlMTBiNjBiYTY2YjYzMWJjOTQ1OWM0
|
11
|
+
YTI3MDA3ZTc3MjAxYmU2OTkyY2VlYjZlM2ZiY2ZmMDRhYTExM2I=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZWI2MTI3NDBhODVkM2FiY2E0YjAwMDBjYTU3MDJiYmYzZTU3MzA0OThlN2Iz
|
14
|
+
Y2YyOTQ4ZWMxN2I5ZjliNDlkMzBhNmI0MDQ1YzlkYWE5YmNiNzkxYWNkNmEy
|
15
|
+
OGYwZmFjZjdlOTc3MjBjNWRjYmViMzg5N2IxMWNhYTBhZmFkYWY=
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Gemfile.lock
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Chris Parsons
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
Rack::Usermanual
|
2
|
+
================
|
3
|
+
|
4
|
+
This little piece of middleware helps you expose your cucumber features in a readable 'manual-like' style for your users to consume.
|
5
|
+
|
6
|
+
To use, add the following to your Rack app:
|
7
|
+
|
8
|
+
```
|
9
|
+
# Choose whatever url endpoint you like.
|
10
|
+
map "/help" do
|
11
|
+
use Rack::Usermanual,
|
12
|
+
# `sections`: Sections of the manual: human readable name together
|
13
|
+
# with a path to a folder containing the features.
|
14
|
+
:sections => {
|
15
|
+
"Game manual" => 'features/docs/game-manual',
|
16
|
+
"API documentation" => 'features/docs/api-documentation'
|
17
|
+
},
|
18
|
+
# `index`: Markdown to display on the index page of the help.
|
19
|
+
:index => 'features/docs/README.md',
|
20
|
+
# `views`: Look in here for the layout: layout.erb, layout.haml etc.
|
21
|
+
:views => File.join(Dir.pwd, 'views')
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
25
|
+
Then start your app and point your browser to `/help` and your features should be displayed for you!
|
26
|
+
|
27
|
+
The app will use the layout that you have in layout.{erb,haml} in whichever folder you specify. The CSS in the views is based on bootstrap: you might need to style your features slightly differently to get them to work in the way that you want. In the future it may be possible to completely override the views with your own.
|
28
|
+
|
29
|
+
## Contributing
|
30
|
+
|
31
|
+
We work on pull requests. If you have an idea for something you'd like to contribute, here's how to do it:
|
32
|
+
|
33
|
+
* Fork the project.
|
34
|
+
* Make your feature addition or bug fix.
|
35
|
+
* Add tests for it. This is important so I don't break it in a
|
36
|
+
future version unintentionally.
|
37
|
+
* Commit, do not mess with rakefile, version, or history.
|
38
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
39
|
+
* Send me a pull request. Bonus points for topic branches.
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'gherkin'
|
2
|
+
require 'gherkin/formatter/json_formatter'
|
3
|
+
require 'stringio'
|
4
|
+
require 'json'
|
5
|
+
require 'sinatra'
|
6
|
+
require 'kramdown'
|
7
|
+
|
8
|
+
module Rack
|
9
|
+
class Usermanual < Sinatra::Base
|
10
|
+
VERSION = "0.1.0"
|
11
|
+
|
12
|
+
def initialize(app, options)
|
13
|
+
super(app)
|
14
|
+
@sections = options[:sections]
|
15
|
+
@index = options[:index]
|
16
|
+
@main_views = options[:views]
|
17
|
+
end
|
18
|
+
|
19
|
+
helpers do
|
20
|
+
def find_template(views, name, engine, &block)
|
21
|
+
new_views = [
|
22
|
+
::File.expand_path(::File.join(::File.dirname(__FILE__), '..', '..', '..', 'views')),
|
23
|
+
@main_views
|
24
|
+
].flatten.compact
|
25
|
+
Array(new_views).each { |v| super(v, name, engine, &block) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def h(text)
|
29
|
+
Rack::Utils.escape_html(text)
|
30
|
+
end
|
31
|
+
|
32
|
+
def replace_start(sentence)
|
33
|
+
{
|
34
|
+
/^given / => 'Assume ',
|
35
|
+
/^but / => 'However, ',
|
36
|
+
/^and / => ''
|
37
|
+
}.each do |find, replace|
|
38
|
+
sentence.sub!(find, replace)
|
39
|
+
end
|
40
|
+
sentence
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
get '/?' do
|
45
|
+
haml :index
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_feature(path, page)
|
49
|
+
sio = StringIO.new
|
50
|
+
json_formatter = Gherkin::Formatter::JSONFormatter.new(sio)
|
51
|
+
parser = Gherkin::Parser::Parser.new(json_formatter)
|
52
|
+
raw = ::File.read("#{path}/#{page}.feature")
|
53
|
+
parser.parse(raw, uri, 0)
|
54
|
+
json_formatter.done
|
55
|
+
[raw, JSON.parse(sio.string)]
|
56
|
+
end
|
57
|
+
|
58
|
+
get %r{/([\w-]+)/([\w-]+)/?$} do
|
59
|
+
section_uri, @page = params[:captures]
|
60
|
+
|
61
|
+
section = @sections.select do |human_name, path|
|
62
|
+
::File.basename(path) == section_uri
|
63
|
+
end
|
64
|
+
halt 404 unless section
|
65
|
+
@human_name = section.keys.first
|
66
|
+
path = section.values.first
|
67
|
+
|
68
|
+
@raw, @json = get_feature(path, @page)
|
69
|
+
|
70
|
+
haml :page
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'rack/usermanual/app'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'rack/usermanual'
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rack/usermanual"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rack-usermanual"
|
7
|
+
s.version = Rack::Usermanual::VERSION
|
8
|
+
s.authors = ["Chris Parsons"]
|
9
|
+
s.email = ["chris.p@rsons.org"]
|
10
|
+
s.homepage = "http://github.com/chrismdp/rack-usermanual"
|
11
|
+
s.summary = %q{Rack endpoint to serve your cucumber features as a user manual}
|
12
|
+
s.description = %q{}
|
13
|
+
|
14
|
+
s.rubyforge_project = "rack-usermanual"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
|
18
|
+
s.require_paths = ['lib']
|
19
|
+
|
20
|
+
s.add_dependency 'sinatra'
|
21
|
+
s.add_dependency 'haml'
|
22
|
+
s.add_dependency 'kramdown'
|
23
|
+
s.add_dependency 'gherkin'
|
24
|
+
s.add_dependency 'rack'
|
25
|
+
s.add_development_dependency 'rspec'
|
26
|
+
s.add_development_dependency 'rack-test'
|
27
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rack/test'
|
3
|
+
|
4
|
+
describe Rack::Usermanual do
|
5
|
+
include Rack::Test::Methods
|
6
|
+
|
7
|
+
def app
|
8
|
+
Rack::Usermanual.new(nil, :sections => {'My section' => 'spec/fixtures/features/my-section'})
|
9
|
+
end
|
10
|
+
|
11
|
+
it "grabs a file from the features folder" do
|
12
|
+
get '/help/my-section/test'
|
13
|
+
last_response.should be_ok
|
14
|
+
last_response.body.should include("This is the preamble")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "accepts trailing slashes" do
|
18
|
+
get '/help/my-section/test/'
|
19
|
+
last_response.should be_ok
|
20
|
+
last_response.body.should include("This is the preamble")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "formats that file correctly" do
|
24
|
+
get '/help/my-section/test'
|
25
|
+
last_response.body.should include("Assume something is true")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "does not allow you to get a random filesystem file" do
|
29
|
+
get '/help/../../lib/solweb.rb'
|
30
|
+
last_response.should_not be_ok
|
31
|
+
get '/help/../docs/game-manual/combat.feature'
|
32
|
+
last_response.should_not be_ok
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns 404 if the file doesn't exist" do
|
36
|
+
get '/help/game-manual/cimbat'
|
37
|
+
last_response.should_not be_ok
|
38
|
+
end
|
39
|
+
end
|
data/views/_menu.haml
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
%nav.span3.pull-right
|
2
|
+
%ul.nav.nav-list.affix-top{:'data-offset-top' => 100, :'data-spy' => 'affix'}
|
3
|
+
- @sections.each do |human_name, path|
|
4
|
+
%li.nav-header= human_name
|
5
|
+
- if (features = Dir.glob(path + '/*.feature').sort).empty?
|
6
|
+
%small.muted No docs yet.
|
7
|
+
- features.each do |fn|
|
8
|
+
- name = ::File.basename(fn, '.feature')
|
9
|
+
%li
|
10
|
+
%a{:href => "/help/#{::File.basename(path)}/#{name}"}= name.capitalize.gsub(/[-_]/, ' ')
|
data/views/_pending.haml
ADDED
data/views/index.haml
ADDED
data/views/page.haml
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
%h4.page-header
|
2
|
+
%a{:href => '/help'} Help & support
|
3
|
+
== » #{@human_name} » #{@page.capitalize}
|
4
|
+
|
5
|
+
.container
|
6
|
+
.row
|
7
|
+
= haml :_menu
|
8
|
+
%article.span9.help-text
|
9
|
+
%h1= @json.first['name']
|
10
|
+
= haml :_pending, :locals => { :element => @json.first }
|
11
|
+
= ::Kramdown::Document.new(h(@json.first['description'])).to_html
|
12
|
+
|
13
|
+
- elements = @json.first['elements']
|
14
|
+
- if elements
|
15
|
+
%h4 Some examples:
|
16
|
+
.examples
|
17
|
+
- elements = @json.first['elements']
|
18
|
+
- if elements.first['keyword'] == 'Background'
|
19
|
+
.well.well-small
|
20
|
+
%strong Note:
|
21
|
+
The following examples assume
|
22
|
+
= elements.first['steps'].map{|s| 'that ' + s['name']}.to_sentence + '.'
|
23
|
+
- elements.select { |e| e['keyword'] == 'Scenario' }.each do |example|
|
24
|
+
%h5.example== Example: #{example['name'].downcase}
|
25
|
+
= haml :_pending, :locals => { :element => example }
|
26
|
+
%p
|
27
|
+
%em
|
28
|
+
- if example['steps']
|
29
|
+
- example['steps'].slice_before {|step| step['keyword'] =~ /When|But/ }.each do |chunk|
|
30
|
+
= replace_start(chunk.map { |step| step['keyword'].downcase + step['name'] }.join(', ')).tap {|s| s.sub!(/./, &:upcase) } + '.'
|
31
|
+
- else
|
32
|
+
%span.muted This example hasn't yet been detailed.
|
33
|
+
%hr
|
34
|
+
%footer.muted
|
35
|
+
%small
|
36
|
+
Generated automatically from this project's
|
37
|
+
%a{:href => "http://github.com/cucumber/cucumber"} Cucumber
|
38
|
+
features.
|
39
|
+
View the
|
40
|
+
%a{:href => 'javascript:false', :'data-toggle' => 'collapse', :'data-target' => '#source'} source.
|
41
|
+
%br
|
42
|
+
%br
|
43
|
+
#source.collapse
|
44
|
+
%pre
|
45
|
+
%code= @raw
|
metadata
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-usermanual
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Parsons
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sinatra
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: haml
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: kramdown
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: gherkin
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rack
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rack-test
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: ''
|
112
|
+
email:
|
113
|
+
- chris.p@rsons.org
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- .gitignore
|
119
|
+
- .rspec
|
120
|
+
- Gemfile
|
121
|
+
- LICENSE
|
122
|
+
- README.md
|
123
|
+
- lib/rack-usermanual.rb
|
124
|
+
- lib/rack/usermanual.rb
|
125
|
+
- lib/rack/usermanual/app.rb
|
126
|
+
- rack-usermanual.gemspec
|
127
|
+
- spec/fixtures/features/my-section/test.feature
|
128
|
+
- spec/spec_helper.rb
|
129
|
+
- spec/usermanual_spec.rb
|
130
|
+
- views/_menu.haml
|
131
|
+
- views/_pending.haml
|
132
|
+
- views/index.haml
|
133
|
+
- views/page.haml
|
134
|
+
homepage: http://github.com/chrismdp/rack-usermanual
|
135
|
+
licenses: []
|
136
|
+
metadata: {}
|
137
|
+
post_install_message:
|
138
|
+
rdoc_options: []
|
139
|
+
require_paths:
|
140
|
+
- lib
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ! '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - ! '>='
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
requirements: []
|
152
|
+
rubyforge_project: rack-usermanual
|
153
|
+
rubygems_version: 2.0.3
|
154
|
+
signing_key:
|
155
|
+
specification_version: 4
|
156
|
+
summary: Rack endpoint to serve your cucumber features as a user manual
|
157
|
+
test_files:
|
158
|
+
- spec/fixtures/features/my-section/test.feature
|
159
|
+
- spec/spec_helper.rb
|
160
|
+
- spec/usermanual_spec.rb
|
161
|
+
has_rdoc:
|