tavola 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 72034f39a54a46e120a0355a0faa5b4f9fbbba54
4
+ data.tar.gz: fe450e1fecb760cdf35ea59ffaec7f641dd29d94
5
+ SHA512:
6
+ metadata.gz: 2e1b8af9758ad18a2c58f80c592eeca916fdc9bbbb59e7ea0d8a60b439a1790a416c07541f463aa10d44103ea75e8a49038bff2b9e90461ca87b8162b01d8370
7
+ data.tar.gz: 8c7728e207bf3a3378c2782b76668f438617f559b15e65d38a359fdb8b3cb0bc358c851bee8db552bb5acf30a6cbbdbba266eea751c8680d03e80eb5d42a0203
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'guard'
7
+ gem 'guard-rspec'
8
+ gem 'guard-sass'
9
+
10
+ # Use this to have interactive test feedback
11
+ gem 'guard-livereload'
12
+
13
+ gem 'rspec'
14
+ gem 'flexmock'
15
+ end
@@ -0,0 +1,18 @@
1
+ guard :rspec do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
6
+
7
+ require './spec/support/unicorn_hunter'
8
+ guard 'unicorn_hunter' do
9
+ watch %r(lib/tavola/(.+)\.rb$)
10
+ watch %r(lib/tavola/(.+)\.slim$)
11
+ end
12
+
13
+ guard 'sass', :input => 'lib/tavola/public/stylesheets'
14
+
15
+ guard 'livereload', grace_period: 0.1 do
16
+ watch %r(qed/.*)
17
+ watch %r(lib/.*)
18
+ end
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+
2
+ Copyright (c) 2014 Kaspar Schiess
3
+
4
+ Permission is hereby granted, free of charge, to any person
5
+ obtaining a copy of this software and associated documentation
6
+ files (the "Software"), to deal in the Software without
7
+ restriction, including without limitation the rights to use,
8
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the
10
+ Software is furnished to do so, subject to the following
11
+ conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
+ OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,10 @@
1
+
2
+ SYNOPSIS
3
+
4
+ To use this, run
5
+
6
+ bin/tavola run
7
+
8
+ in a directory of your choice. Then navigate to localhost:8080 and follow
9
+ the on-screen instructions.
10
+
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pathname'
4
+
5
+ binary = Pathname.new(__FILE__)
6
+ $:.unshift binary.dirname.dirname.join('lib')
7
+
8
+ require 'tavola/cli'
9
+
10
+ Tavola::CLI.run
@@ -0,0 +1,39 @@
1
+
2
+ require 'clamp'
3
+ require 'rack'
4
+ require 'unicorn'
5
+ require 'pathname'
6
+
7
+ module Tavola
8
+
9
+ class CLI < Clamp::Command
10
+ subcommand 'run', <<-DESC.strip do
11
+ runs tavola on either the current directory or the given directory.
12
+ DESC
13
+
14
+ def execute
15
+ app = lambda do ||
16
+ require 'tavola/configuration'
17
+ require 'tavola/web'
18
+
19
+ Tavola::Web.set :tavola_config,
20
+ Tavola::Configuration.new(
21
+ base_dir: Pathname.new(Dir.pwd))
22
+
23
+ Rack::Builder.new do
24
+ use Rack::ContentLength
25
+ use Rack::Chunked
26
+ use Rack::CommonLogger, $stderr
27
+ use Rack::ShowExceptions
28
+ use Rack::Lint
29
+
30
+ run Tavola::Web
31
+ end.to_app
32
+ end
33
+
34
+ Unicorn::HttpServer.new(app).start.join
35
+ end
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,10 @@
1
+
2
+ module Tavola
3
+ class Configuration
4
+ attr_reader :base_dir
5
+
6
+ def initialize opts={}
7
+ @base_dir = opts[:base_dir]
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,81 @@
1
+
2
+ require 'stringio'
3
+
4
+ require 'qed/settings'
5
+ require 'qed/session'
6
+ require 'tavola/qed/reporter'
7
+
8
+ module Tavola
9
+ class Demonstrations
10
+ def initialize config
11
+ @config = config
12
+ end
13
+
14
+ def root
15
+ root = @config.base_dir
16
+ end
17
+
18
+ def all
19
+ Dir[root.join('**/*.md')].map { |path|
20
+ Demonstration.new(@config, path) }
21
+ end
22
+
23
+ def find path
24
+ Demonstration.new(@config, root.join(path))
25
+ end
26
+
27
+ end
28
+
29
+ class Demonstration
30
+ attr_reader :path
31
+
32
+ def initialize config, path
33
+ @config = config
34
+ @path = path
35
+ end
36
+
37
+ def root
38
+ root = @config.base_dir
39
+ end
40
+ attr_reader :path
41
+
42
+ def relative_path
43
+ remove_root(path)
44
+ end
45
+
46
+ def render
47
+ qed_augment(path)
48
+ # File.read(path)
49
+ end
50
+
51
+ def qed_augment path
52
+ # Mostly a copy from Session#run in QED.
53
+ settings = ::QED::Settings.new()
54
+ session = ::QED::Session.new(settings)
55
+
56
+ io = StringIO.new
57
+ reporter = QED::Reporter.new(io: io)
58
+
59
+ session.prepare_loadpath
60
+ session.require_libraries
61
+
62
+ demo = ::QED::Demo.new(path, at: root)
63
+ demo.steps
64
+
65
+ ::QED::Evaluator.run(demo, observers: [reporter], settings: settings)
66
+
67
+ p io
68
+ io.string
69
+ end
70
+
71
+ private
72
+ def remove_root path
73
+ root_len = root.to_s.size
74
+
75
+ stripped = path[root_len..-1]
76
+ return stripped[1..-1] if stripped.start_with? '/'
77
+
78
+ stripped
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,30 @@
1
+ require 'rouge'
2
+
3
+ # This little hack here plugs the rouge syntax highlighter into the kramdown
4
+ # markdown converter.
5
+ Kramdown::Converter::Html.class_eval do
6
+ def convert_codeblock(el, indent)
7
+ attr = el.attr.dup
8
+ language = extract_code_language!(attr)
9
+ highlight(el.value, language)
10
+ end
11
+
12
+ def highlight(code, language=nil, opts={})
13
+ lexer = Rouge::Lexer.find_fancy(language, code) || Rouge::Lexers::PlainText
14
+
15
+ options = {
16
+ line_numbers: false,
17
+ css_class: 'highlight',
18
+ inline_theme: nil,
19
+ wrap: true,
20
+ lexer_options: {}
21
+ }
22
+
23
+ highlighter_options = options.to_h.merge(opts)
24
+ highlighter_options[:css_class] = [ highlighter_options[:css_class], lexer.tag ].join(' ')
25
+ lexer_options = highlighter_options.delete(:lexer_options)
26
+
27
+ formatter = Rouge::Formatters::HTML.new(highlighter_options)
28
+ formatter.format(lexer.lex(code, lexer_options))
29
+ end
30
+ end
@@ -0,0 +1,4 @@
1
+ .example.green pre {
2
+ border: 1px solid green; }
3
+ .example.red pre {
4
+ border: 1px solid red; }
@@ -0,0 +1,9 @@
1
+
2
+ .example
3
+ &.green
4
+ pre
5
+ border: 1px solid green
6
+
7
+ &.red
8
+ pre
9
+ border: 1px solid red
@@ -0,0 +1,163 @@
1
+
2
+ require 'qed/reporter/abstract'
3
+
4
+ module Tavola
5
+ module QED
6
+ class Reporter < ::QED::Reporter::Abstract
7
+
8
+ #
9
+ def before_session(session)
10
+ @start_time = Time.now
11
+ end
12
+
13
+ def step(step)
14
+ @_explain = step.explain.dup
15
+ end
16
+
17
+ #
18
+ def match(step, md)
19
+ unless md[0].empty?
20
+ @_explain.sub!(md[0], md[0])
21
+ end
22
+ end
23
+
24
+ #
25
+ def applique(step)
26
+ io.print "#{@_explain}"
27
+ io.print "#{step.example}" #
28
+ end
29
+
30
+ #
31
+ def pass(step)
32
+ super(step)
33
+ print_step_heading(step)
34
+
35
+ if step.has_example?
36
+ wrap_example 'green' do
37
+ print_step_example(step)
38
+ end
39
+ end
40
+ end
41
+
42
+ #
43
+ def fail(step, error)
44
+ super(step, error)
45
+
46
+ tab = step.text.index(/\S/)
47
+
48
+ print_step_heading(step)
49
+
50
+ if step.has_example?
51
+ wrap_example('red') do
52
+ print_step_example(step)
53
+ end
54
+ end
55
+
56
+ msg = []
57
+ msg << "FAIL: " + error.message.to_s #to_str
58
+ msg << sane_backtrace(error).join("\n")
59
+ msg = msg.join("\n")
60
+
61
+ wrap_failure(msg)
62
+ end
63
+
64
+ #
65
+ def error(step, error)
66
+ super(step, error)
67
+
68
+ raise error if $DEBUG # TODO: Should this be here?
69
+
70
+ tab = step.text.index(/\S/)
71
+
72
+ print_step_heading(step)
73
+
74
+ if step.has_example?
75
+ wrap_example('red') do
76
+ print_step_example(step)
77
+ end
78
+ end
79
+
80
+ msg = []
81
+ msg << "ERROR: #{error.class} " + error.message #.sub(/for QED::Context.*?$/,'')
82
+ msg << sane_backtrace(error).join("\n")
83
+ msg = msg.join("\n") #
84
+
85
+ wrap_failure(msg)
86
+ end
87
+
88
+ def after_session(session)
89
+ trap 'INFO', 'DEFAULT' if INFO_SIGNAL
90
+ print_time
91
+ print_tally
92
+ end
93
+
94
+ private
95
+
96
+ def wrap_failure text
97
+ text = text.
98
+ gsub(%r(^FAIL: (.*)$)) { md = $~
99
+ %Q(<span class="text-danger">FAIL</span>: <span class="text-warning">#{md[1]}</span>)}.
100
+ gsub(%r(^ERROR: (\w+) (.*)$)) { md = $~
101
+ %Q(<span class="text-danger">ERROR</span>: (<span class="text-primary">#{md[1]}</span>) <span class="text-warning">#{md[2]}</span>) }
102
+ io.puts '<pre>'
103
+ io.puts text
104
+ io.puts '</pre>'
105
+ io.puts
106
+ end
107
+ def wrap_code_block language=nil
108
+ io.puts '~~~' + language.to_s
109
+ yield
110
+ io.puts '~~~'
111
+ io.puts
112
+ end
113
+ def clean_whitespace example
114
+ indent = nil
115
+ lines = example.lines.
116
+ map { |l|
117
+ md = l.match(/^( +)/)
118
+ indent = md[1].size unless indent
119
+
120
+ l[indent..-1] }.join
121
+ end
122
+ def print_step_example step
123
+ if step.data?
124
+ wrap_code_block do
125
+ io.print "#{clean_whitespace(step.example)}"
126
+ end
127
+ else
128
+ wrap_code_block 'ruby' do
129
+ io.print "#{clean_whitespace(step.example)}"
130
+ end
131
+ end
132
+ end
133
+ def print_step_heading step
134
+ if step.heading?
135
+ if step.code?
136
+ io.print "#{@_explain}"
137
+ else
138
+ io.print "#{@_explain}"
139
+ end
140
+ else
141
+ io.print "#{@_explain}"
142
+ end
143
+ end
144
+ def wrap_example color
145
+ io.puts %Q({::options parse_block_html="true" /})
146
+ io.puts %Q(<div class="example #{color}">)
147
+
148
+ yield
149
+
150
+ io.puts %Q(</div>)
151
+ io.puts
152
+ end
153
+
154
+
155
+ end
156
+
157
+ end # module QED
158
+ end # module Tavola
159
+
160
+ # Install the reporter below QED::Reporter - it was kind of obvious we'd have
161
+ # to do this.
162
+ QED::Reporter::Enhance = Tavola::QED::Reporter
163
+
@@ -0,0 +1,7 @@
1
+
2
+ p
3
+ h1
4
+ | Tavola
5
+ small the table where QEDs display
6
+
7
+ | Please select a demonstration on the left.
@@ -0,0 +1,25 @@
1
+ doctype html
2
+ html
3
+ head
4
+ title La Tavola
5
+
6
+ link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"
7
+ script src="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"
8
+
9
+ link rel="stylesheet" href="/stylesheets/rouge.css"
10
+ link rel="stylesheet" href="/stylesheets/tavola.css"
11
+
12
+ body
13
+ .container
14
+ .row
15
+ / X-file Navigation
16
+ .col-md-3
17
+ h1 Other QEDs
18
+ ul.nav
19
+ - for demonstration in @all
20
+ li
21
+ a href="/#{demonstration.relative_path}"= demonstration.relative_path
22
+
23
+ / Content
24
+ .col-md-9
25
+ == yield
@@ -0,0 +1 @@
1
+ <%= Rouge::Themes::Github.render(:scope => '.highlight') %>
@@ -0,0 +1,40 @@
1
+
2
+ require 'sinatra/base'
3
+
4
+ require 'slim'
5
+ require 'kramdown'
6
+ Tilt.prefer Tilt::KramdownTemplate
7
+ require 'tavola/kramdown_rouge'
8
+
9
+ require 'tavola/demonstrations'
10
+
11
+ module Tavola
12
+ class Web < Sinatra::Base
13
+ before do
14
+ @all = demonstrations.all
15
+ end
16
+
17
+ get '/' do
18
+ slim :'index'
19
+ end
20
+
21
+ get '/stylesheets/rouge.css' do
22
+ content_type 'text/css'
23
+ erb :'stylesheets/rouge.css'
24
+ end
25
+
26
+ get '*' do
27
+ return pass unless params[:splat].first.match(/.*\.md$/)
28
+
29
+ path = params[:splat].first[1..-1] # relative path
30
+ demonstration = demonstrations.find(path)
31
+
32
+ markdown demonstration.render, layout_engine: :slim, layout: :layout
33
+ end
34
+
35
+ private
36
+ def demonstrations
37
+ Demonstrations.new(settings.tavola_config)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,27 @@
1
+
2
+ # When all is good
3
+
4
+ then the example will be highlighted in green.
5
+
6
+ 1.assert == 1
7
+
8
+ # When the assertion fails
9
+
10
+ the example will be highlighted in red. The assertion failure is printed right after the example.
11
+
12
+ 1.assert == 3
13
+
14
+ # When an exception is raised
15
+
16
+ the example will be red as well. Exception backtrace is printed below.
17
+
18
+ fail "Some error has occurred."
19
+
20
+ # Installation Tips
21
+
22
+ Use [`guard-livereload`](https://github.com/guard/guard-livereload) and the Chrome LiveReload extension to get immediate test feedback upon saving. Your `Guardfile` would look like this:
23
+
24
+ guard 'livereload', grace_period: 0.1 do
25
+ watch %r(qed/.*)
26
+ end
27
+
@@ -0,0 +1,14 @@
1
+ require 'guard/guard'
2
+
3
+ module Guard
4
+ class UnicornHunter < Guard
5
+ # Called on file(s) modifications that the Guard watches.
6
+ # @param [Array<String>] paths the changes files or paths
7
+ # @raise [:task_has_failed] when run_on_change has failed
8
+ def run_on_change(paths)
9
+ if system("killall -m 'tavola worker'")
10
+ puts "Unicorn hunter has found a unicorn..."
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "tavola"
5
+ s.version = '0.1.0'
6
+ s.summary = "Interactive runner for qed tests"
7
+ # s.homepage = "http://todo.project.com/"
8
+ s.authors = ['Kaspar Schiess']
9
+ s.email = ["kaspar.schiess@absurd.li"]
10
+
11
+ s.files = Dir['**/*']
12
+ s.test_files = Dir['test/**/*'] + Dir['spec/**/*']
13
+ s.executables = Dir['bin/*'].map { |f| File.basename(f) }
14
+ s.require_paths = ["lib"]
15
+
16
+ s.add_runtime_dependency 'ae', '>= 1.8'
17
+ s.add_runtime_dependency 'qed', '>= 2.9'
18
+
19
+ s.add_runtime_dependency 'sinatra', '> 1.2', '< 1.5'
20
+ s.add_runtime_dependency 'padrino-helpers'
21
+
22
+ s.add_runtime_dependency 'clamp'
23
+
24
+ s.add_runtime_dependency 'kramdown'
25
+ s.add_runtime_dependency 'rouge'
26
+ s.add_runtime_dependency 'slim'
27
+
28
+ s.add_runtime_dependency 'unicorn'
29
+ s.add_runtime_dependency 'rack'
30
+ end
metadata ADDED
@@ -0,0 +1,210 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tavola
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kaspar Schiess
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ae
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: qed
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '2.9'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '2.9'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sinatra
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.2'
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '1.5'
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">"
56
+ - !ruby/object:Gem::Version
57
+ version: '1.2'
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.5'
61
+ - !ruby/object:Gem::Dependency
62
+ name: padrino-helpers
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: clamp
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: kramdown
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: rouge
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: slim
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :runtime
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: unicorn
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :runtime
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ - !ruby/object:Gem::Dependency
146
+ name: rack
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :runtime
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ description:
160
+ email:
161
+ - kaspar.schiess@absurd.li
162
+ executables:
163
+ - tavola
164
+ extensions: []
165
+ extra_rdoc_files: []
166
+ files:
167
+ - Gemfile
168
+ - Guardfile
169
+ - LICENSE
170
+ - README
171
+ - bin/tavola
172
+ - lib/tavola/cli.rb
173
+ - lib/tavola/configuration.rb
174
+ - lib/tavola/demonstrations.rb
175
+ - lib/tavola/kramdown_rouge.rb
176
+ - lib/tavola/public/stylesheets/tavola.css
177
+ - lib/tavola/public/stylesheets/tavola.sass
178
+ - lib/tavola/qed/reporter.rb
179
+ - lib/tavola/views/index.slim
180
+ - lib/tavola/views/layout.slim
181
+ - lib/tavola/views/stylesheets/rouge.css.erb
182
+ - lib/tavola/web.rb
183
+ - qed/example.md
184
+ - spec/support/unicorn_hunter.rb
185
+ - tavola.gemspec
186
+ homepage:
187
+ licenses: []
188
+ metadata: {}
189
+ post_install_message:
190
+ rdoc_options: []
191
+ require_paths:
192
+ - lib
193
+ required_ruby_version: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ required_rubygems_version: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - ">="
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ requirements: []
204
+ rubyforge_project:
205
+ rubygems_version: 2.2.2
206
+ signing_key:
207
+ specification_version: 4
208
+ summary: Interactive runner for qed tests
209
+ test_files:
210
+ - spec/support/unicorn_hunter.rb