rspec-documentation 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/Gemfile.lock +3 -3
- data/Makefile +9 -0
- data/README.md +17 -21
- data/exe/rspec-documentation +13 -1
- data/lib/rspec/documentation/version.rb +1 -1
- data/lib/rspec/documentation.rb +1 -51
- data/lib/rspec_documentation/configuration.rb +17 -4
- data/lib/rspec_documentation/document.rb +18 -4
- data/lib/rspec_documentation/documentation.rb +85 -0
- data/lib/rspec_documentation/formatters/ansi.rb +44 -0
- data/lib/rspec_documentation/formatters/html.rb +31 -0
- data/lib/rspec_documentation/formatters/json.rb +32 -0
- data/lib/rspec_documentation/formatters/ruby.rb +31 -0
- data/lib/rspec_documentation/formatters/yaml.rb +36 -0
- data/lib/rspec_documentation/formatters.rb +20 -0
- data/lib/rspec_documentation/html_element.rb +21 -18
- data/lib/rspec_documentation/javascript_bundle.rb +17 -0
- data/lib/rspec_documentation/page_collection.rb +24 -9
- data/lib/rspec_documentation/page_tree.rb +16 -8
- data/lib/rspec_documentation/page_tree_element.rb +31 -9
- data/lib/rspec_documentation/parsed_document.rb +5 -3
- data/lib/rspec_documentation/project_initialization.rb +52 -0
- data/lib/rspec_documentation/rspec/failure.rb +20 -5
- data/lib/rspec_documentation/rspec.rb +0 -2
- data/lib/rspec_documentation/spec.rb +58 -12
- data/lib/rspec_documentation/stylesheet_bundle.rb +17 -0
- data/lib/rspec_documentation/summary.rb +87 -0
- data/lib/rspec_documentation/util.rb +12 -0
- data/lib/rspec_documentation.rb +16 -3
- data/lib/templates/000-Introduction.md.erb +35 -0
- data/lib/templates/010-Usage.md.erb +3 -0
- data/lib/templates/500-License.md.erb +3 -0
- data/lib/templates/bootstrap.js.erb +7 -0
- data/lib/templates/footer.html.erb +5 -0
- data/lib/templates/header.html.erb +16 -3
- data/lib/templates/layout.css.erb +381 -2
- data/lib/templates/layout.html.erb +13 -82
- data/lib/templates/layout.js.erb +67 -0
- data/lib/templates/modal_spec.html.erb +51 -0
- data/lib/templates/moon.svg.erb +1 -0
- data/lib/templates/script_tags.html.erb +1 -0
- data/lib/templates/stylesheet_links.html.erb +1 -0
- data/lib/templates/sun.svg.erb +1 -0
- data/lib/templates/tabbed_spec.html.erb +12 -49
- data/lib/templates/themes/bootstrap.min.css +11 -0
- data/lib/templates/themes/cerulean.css +5 -6
- data/lib/templates/themes/cosmo.css +5 -6
- data/lib/templates/themes/cyborg.css +5 -6
- data/lib/templates/themes/darkly.css +5 -6
- data/lib/templates/themes/flatly.css +5 -6
- data/lib/templates/themes/journal.css +5 -6
- data/lib/templates/themes/litera.css +5 -6
- data/lib/templates/themes/lumen.css +5 -6
- data/lib/templates/themes/lux.css +5 -6
- data/lib/templates/themes/materia.css +5 -6
- data/lib/templates/themes/minty.css +5 -6
- data/lib/templates/themes/morph.css +5 -6
- data/lib/templates/themes/pulse.css +5 -6
- data/lib/templates/themes/quartz.css +5 -6
- data/lib/templates/themes/sandstone.css +5 -6
- data/lib/templates/themes/simplex.css +5 -6
- data/lib/templates/themes/sketchy.css +5 -6
- data/lib/templates/themes/slate.css +5 -6
- data/lib/templates/themes/solar.css +5 -6
- data/lib/templates/themes/spacelab.css +5 -6
- data/lib/templates/themes/superhero.css +5 -6
- data/lib/templates/themes/united.css +5 -6
- data/lib/templates/themes/vapor.css +5 -6
- data/lib/templates/themes/yeti.css +5 -6
- data/lib/templates/themes/zephyr.css +5 -6
- data/rspec-documentation/pages/000-Introduction/000-Quickstart.md +17 -0
- data/rspec-documentation/pages/000-Introduction.md +14 -30
- data/rspec-documentation/pages/010-File System/000-Ordering.md +1 -1
- data/rspec-documentation/pages/010-File System/010-Documentation Bundle.md +9 -0
- data/rspec-documentation/pages/010-File System.md +1 -1
- data/rspec-documentation/pages/020-Running Tests.md +41 -0
- data/rspec-documentation/pages/030-Examples/010-Basic.md +51 -0
- data/rspec-documentation/pages/030-Examples/020-HTML.md +45 -0
- data/rspec-documentation/pages/030-Examples/030-ANSI.md +33 -0
- data/rspec-documentation/pages/030-Examples/040-JSON.md +39 -0
- data/rspec-documentation/pages/030-Examples/050-YAML.md +40 -0
- data/rspec-documentation/pages/030-Examples.md +7 -0
- data/rspec-documentation/pages/040-Spec Helper.md +11 -0
- data/rspec-documentation/pages/050-Linking.md +20 -0
- data/rspec-documentation/pages/060-Configuration/010-Context.md +26 -0
- data/rspec-documentation/pages/060-Configuration/020-Build Paths.md +33 -0
- data/rspec-documentation/pages/060-Configuration/030-Attribution.md +23 -0
- data/rspec-documentation/pages/060-Configuration.md +13 -0
- data/rspec-documentation/pages/070-Publishing.md +13 -0
- data/rspec-documentation/pages/500-License.md +11 -0
- data/rspec-documentation/spec_helper.rb +8 -0
- data/rspec-documentation.gemspec +2 -1
- metadata +46 -12
- data/lib/rspec_documentation/ansi_html.rb +0 -28
- data/lib/rspec_documentation/context.rb +0 -44
- data/lib/rspec_documentation/rspec/example_group.rb +0 -26
- data/lib/rspec_documentation/rspec/reporter.rb +0 -45
- data/rspec-documentation/pages/010-File System/010-Standalone Directories.md +0 -17
- data/rspec-documentation/pages/010-File System/020-Standalone Directory/Example Page.md +0 -3
- data/rspec-documentation/pages/020-Running Specs.md +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a964ddab12c98c8913f741374a4206eaff591787f10e692417d9cf097fd2fe45
|
4
|
+
data.tar.gz: 5dd25967d474700f60118b12649906f072bf912a173651bcf5ea1e70889c7ecb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1923b974e68f71be19dfeddc8379d242c54c3ce69770490399237897d46672177c15fa4990260bef4442414746e273e2e1f0764b67ac134a28c4d2c0a2336b09
|
7
|
+
data.tar.gz: 5f25067b064fa2acca91e6b82a45d1bf5218005885262b638589b0a94b746daf9c2c7da21b34b64865cec1e3d924c5f960adc30505c5ced25a146059c4a10bd6
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rspec-documentation (0.0.
|
4
|
+
rspec-documentation (0.0.3)
|
5
5
|
htmlbeautifier (~> 1.4)
|
6
6
|
kramdown (~> 2.4)
|
7
7
|
kramdown-parser-gfm (~> 1.1)
|
8
|
-
paintbrush (~> 0.1.
|
8
|
+
paintbrush (~> 0.1.3)
|
9
9
|
redcarpet (~> 3.6)
|
10
10
|
rouge (~> 4.1)
|
11
11
|
rspec (~> 3.12)
|
@@ -26,7 +26,7 @@ GEM
|
|
26
26
|
kramdown-parser-gfm (1.1.0)
|
27
27
|
kramdown (~> 2.0)
|
28
28
|
paint (2.3.0)
|
29
|
-
paintbrush (0.1.
|
29
|
+
paintbrush (0.1.3)
|
30
30
|
parallel (1.23.0)
|
31
31
|
parser (3.2.2.1)
|
32
32
|
ast (~> 2.4.1)
|
data/Makefile
CHANGED
@@ -1,5 +1,14 @@
|
|
1
|
+
project=rspec-documentation
|
2
|
+
|
1
3
|
.PHONY: test
|
2
4
|
test:
|
3
5
|
bundle exec rspec
|
4
6
|
bundle exec rubocop
|
5
7
|
bundle exec strong_versions
|
8
|
+
exe/rspec-documentation
|
9
|
+
|
10
|
+
.PHONY: publish
|
11
|
+
publish:
|
12
|
+
@RSPEC_DOCUMENTATION_URL_ROOT='/$(project)' exe/rspec-documentation
|
13
|
+
@rsync --delete -r rspec-documentation/bundle/ docs01.bob.frl:/mnt/docs/$(project)/
|
14
|
+
@echo 'Published.'
|
data/README.md
CHANGED
@@ -1,31 +1,27 @@
|
|
1
1
|
# RSpec::Documentation
|
2
2
|
|
3
|
-
|
3
|
+
_RSpec Documentation_ provides a simple but powerful system for generating _Ruby_ documentation using [_RSpec_](https://rspec.info/) designed to help you ensure that all code examples in your documentation really work.
|
4
4
|
|
5
|
-
|
5
|
+
* Create a tree of _Markdown_ files in your project directory under `rspec-documentation/pages/`.
|
6
|
+
* Embed tests in ```` ```rspec ```` code blocks (other output formatters are available - see examples).
|
7
|
+
* Define a `subject` for each test.
|
8
|
+
* Run the provided `rspec-documentation` command.
|
6
9
|
|
7
|
-
|
10
|
+
There is no _DSL_ to learn and vanilla _RSpec_ examples are used to generate inputs and outputs. No _Markdown_ language extensions are used, simply define the language of a fenced code block as `rspec` in any `.md` file and _RSpecDocumentation_ will do the rest.
|
8
11
|
|
9
|
-
|
12
|
+
## Quick Example
|
10
13
|
|
11
|
-
|
14
|
+
The following is an example _Markdown_ file.
|
12
15
|
|
13
|
-
|
16
|
+
````console
|
17
|
+
# An example test
|
14
18
|
|
15
|
-
|
19
|
+
This is a very simple test:
|
16
20
|
|
17
|
-
|
21
|
+
```rspec
|
22
|
+
subject { 'my subject' }
|
23
|
+
it { is_expected.to eql 'my subject' }
|
24
|
+
```
|
25
|
+
````
|
18
26
|
|
19
|
-
|
20
|
-
|
21
|
-
TODO: Write usage instructions here
|
22
|
-
|
23
|
-
## Development
|
24
|
-
|
25
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
26
|
-
|
27
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
28
|
-
|
29
|
-
## Contributing
|
30
|
-
|
31
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/rspec-documentation.
|
27
|
+
View the [full documentation](https://docs.bob.frl/rspec-documentation) (built using Rspec Documentation!) for detailed usage instructions.
|
data/exe/rspec-documentation
CHANGED
@@ -2,4 +2,16 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require_relative '../lib/rspec/documentation'
|
5
|
-
|
5
|
+
|
6
|
+
# Try to load Rails and config/environment.rb, but don't panic if not present, we only use Rails
|
7
|
+
# to fetch things like application name etc.
|
8
|
+
begin
|
9
|
+
require 'rails'
|
10
|
+
require Pathname.new(Dir.pwd).join('config/environment')
|
11
|
+
rescue LoadError # rubocop:disable Lint/SuppressedException
|
12
|
+
end
|
13
|
+
|
14
|
+
documentation = RSpec::Documentation.generate_documentation
|
15
|
+
|
16
|
+
exit 1 if documentation.failed?
|
17
|
+
exit 0
|
data/lib/rspec/documentation.rb
CHANGED
@@ -11,63 +11,13 @@ module RSpec
|
|
11
11
|
class Error < StandardError; end
|
12
12
|
|
13
13
|
class << self
|
14
|
-
include Paintbrush
|
15
|
-
|
16
14
|
def generate_documentation
|
17
|
-
|
18
|
-
page_collection.generate
|
19
|
-
page_collection.flush unless failed?
|
20
|
-
print_summary
|
21
|
-
nil
|
22
|
-
end
|
23
|
-
|
24
|
-
def require_spec_helper
|
25
|
-
path = Pathname.new(Dir.pwd).join('rspec-documentation/spec_helper.rb')
|
26
|
-
require path if path.file?
|
15
|
+
RSpecDocumentation::Documentation.new.tap(&:generate)
|
27
16
|
end
|
28
17
|
|
29
18
|
def configure(&block)
|
30
19
|
RSpecDocumentation.configure(&block)
|
31
20
|
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def print_success_summary
|
36
|
-
warn(paintbrush { green("\n Created #{blue(page_paths.size)} pages.\n") })
|
37
|
-
warn(paintbrush { cyan(" View your documentation here: #{white(bundle_index_path)}\n") })
|
38
|
-
end
|
39
|
-
|
40
|
-
def print_failure_summary
|
41
|
-
page_collection.failures.each do |failure|
|
42
|
-
$stderr.write(failure.message)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def bundle_index_path
|
47
|
-
RSpecDocumentation::Util.bundle_dir.glob('*.html').first.expand_path
|
48
|
-
end
|
49
|
-
|
50
|
-
def page_paths
|
51
|
-
@page_paths ||= Pathname.new(Dir.pwd).join('rspec-documentation/pages').glob('**/*.md')
|
52
|
-
end
|
53
|
-
|
54
|
-
def page_collection
|
55
|
-
@page_collection ||= RSpecDocumentation::PageCollection.new(page_paths: page_paths)
|
56
|
-
end
|
57
|
-
|
58
|
-
def failed?
|
59
|
-
!page_collection.failures.empty?
|
60
|
-
end
|
61
|
-
|
62
|
-
def print_summary
|
63
|
-
if failed?
|
64
|
-
print_failure_summary
|
65
|
-
else
|
66
|
-
print_success_summary
|
67
|
-
end
|
68
|
-
|
69
|
-
nil
|
70
|
-
end
|
71
21
|
end
|
72
22
|
end
|
73
23
|
end
|
@@ -4,12 +4,25 @@ module RSpecDocumentation
|
|
4
4
|
# Configures the rspec-documentation gem, allows setting a context that makes values available to each example.
|
5
5
|
class Configuration
|
6
6
|
def initialize
|
7
|
-
@
|
7
|
+
@context_defined = false
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
10
|
+
def context_defined?
|
11
|
+
@context_defined
|
12
|
+
end
|
13
|
+
|
14
|
+
def attribution
|
15
|
+
return @attribution if defined?(@attribution)
|
16
|
+
|
17
|
+
'Documentation generated by ' \
|
18
|
+
'<a target="_blank" href="https://github.com/bobf/rspec-documentation">rspec-documentation</a>'
|
19
|
+
end
|
20
|
+
|
21
|
+
def context(&block)
|
22
|
+
raise Error, 'RSpecDocumentation context has already been defined.' if context_defined?
|
23
|
+
|
24
|
+
@context_defined = true
|
25
|
+
::RSpec.shared_context('__rspec_documentation', &block)
|
13
26
|
end
|
14
27
|
end
|
15
28
|
end
|
@@ -5,8 +5,9 @@ module RSpecDocumentation
|
|
5
5
|
class Document
|
6
6
|
attr_reader :failures, :page_tree
|
7
7
|
|
8
|
-
def initialize(document:, page_tree:)
|
8
|
+
def initialize(document:, path:, page_tree:)
|
9
9
|
@document = document
|
10
|
+
@path = path
|
10
11
|
@page_tree = page_tree
|
11
12
|
@failures = []
|
12
13
|
end
|
@@ -30,7 +31,8 @@ module RSpecDocumentation
|
|
30
31
|
end
|
31
32
|
|
32
33
|
def title
|
33
|
-
|
34
|
+
return ::Rails.application.class.module_parent.name.titleize if defined?(::Rails)
|
35
|
+
|
34
36
|
gem_spec&.name
|
35
37
|
end
|
36
38
|
|
@@ -38,6 +40,10 @@ module RSpecDocumentation
|
|
38
40
|
gem_spec&.version
|
39
41
|
end
|
40
42
|
|
43
|
+
def homepage
|
44
|
+
gem_spec&.homepage
|
45
|
+
end
|
46
|
+
|
41
47
|
def header
|
42
48
|
RSpecDocumentation.template('header').result(binding)
|
43
49
|
end
|
@@ -46,12 +52,20 @@ module RSpecDocumentation
|
|
46
52
|
RSpecDocumentation.template('footer').result(binding)
|
47
53
|
end
|
48
54
|
|
55
|
+
def stylesheet_bundle_href
|
56
|
+
Util.assets_root.join('bundle.css')
|
57
|
+
end
|
58
|
+
|
59
|
+
def javascript_bundle_src
|
60
|
+
Util.assets_root.join('bundle.js')
|
61
|
+
end
|
62
|
+
|
49
63
|
private
|
50
64
|
|
51
|
-
attr_reader :document
|
65
|
+
attr_reader :document, :path
|
52
66
|
|
53
67
|
def parsed_document
|
54
|
-
@parsed_document ||= ParsedDocument.new(document)
|
68
|
+
@parsed_document ||= ParsedDocument.new(document, path: path)
|
55
69
|
end
|
56
70
|
|
57
71
|
def gem_spec
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpecDocumentation
|
4
|
+
# Generates documentation from Markdown files, main entry point to documentation generator.
|
5
|
+
class Documentation
|
6
|
+
include Paintbrush
|
7
|
+
|
8
|
+
def generate
|
9
|
+
initialize_if_empty
|
10
|
+
start
|
11
|
+
require_spec_helper
|
12
|
+
ensure_context
|
13
|
+
page_collection.generate
|
14
|
+
flush unless failed?
|
15
|
+
summary.flush
|
16
|
+
rescue RSpecDocumentation::MissingFileError => e
|
17
|
+
warn(paintbrush { red e.message })
|
18
|
+
@failed = true
|
19
|
+
end
|
20
|
+
|
21
|
+
def failed?
|
22
|
+
@failed || !page_collection.failures.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def require_spec_helper
|
28
|
+
path = pwd.join('rspec-documentation/spec_helper.rb')
|
29
|
+
require path if path.file?
|
30
|
+
end
|
31
|
+
|
32
|
+
# Ensure `__rspec_documentation` shared context is always defined.
|
33
|
+
# See lib/rspec_documenation/spec.rb
|
34
|
+
def ensure_context
|
35
|
+
return if RSpecDocumentation.configuration.context_defined?
|
36
|
+
|
37
|
+
RSpecDocumentation.configuration.context {} # rubocop:disable Lint/EmptyBlock
|
38
|
+
end
|
39
|
+
|
40
|
+
def start
|
41
|
+
warn(paintbrush { white "\nRunning specs..." })
|
42
|
+
@started_at = Time.now.utc
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize_if_empty
|
46
|
+
return if Util.base_dir.exist?
|
47
|
+
|
48
|
+
ProjectInitialization.new.flush
|
49
|
+
end
|
50
|
+
|
51
|
+
def summary
|
52
|
+
@summary ||= RSpecDocumentation::Summary.new(
|
53
|
+
page_collection: page_collection,
|
54
|
+
pwd: pwd,
|
55
|
+
started_at: @started_at
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def flush
|
60
|
+
page_collection.flush
|
61
|
+
stylesheet_bundle.flush
|
62
|
+
javascript_bundle.flush
|
63
|
+
end
|
64
|
+
|
65
|
+
def stylesheet_bundle
|
66
|
+
@stylesheet_bundle ||= RSpecDocumentation::StylesheetBundle.new
|
67
|
+
end
|
68
|
+
|
69
|
+
def javascript_bundle
|
70
|
+
@javascript_bundle ||= RSpecDocumentation::JavascriptBundle.new
|
71
|
+
end
|
72
|
+
|
73
|
+
def page_paths
|
74
|
+
@page_paths ||= pwd.join('rspec-documentation/pages').glob('**/*.md')
|
75
|
+
end
|
76
|
+
|
77
|
+
def page_collection
|
78
|
+
@page_collection ||= RSpecDocumentation::PageCollection.new(page_paths: page_paths)
|
79
|
+
end
|
80
|
+
|
81
|
+
def pwd
|
82
|
+
@pwd ||= Pathname.new(Dir.pwd)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpecDocumentation
|
4
|
+
module Formatters
|
5
|
+
COLOR_CODES = [0, 1, 2, 3, 4, 5, 6, 7, 9].freeze
|
6
|
+
|
7
|
+
# Outputs a string containing ANSI color code escape sequences into HTML with attached
|
8
|
+
# classes for each matched color code. Cleans any remaining escape codes.
|
9
|
+
class Ansi
|
10
|
+
def initialize(subject:)
|
11
|
+
@subject = subject
|
12
|
+
end
|
13
|
+
|
14
|
+
def prettified_output
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def rendered_output
|
19
|
+
"<div class='ansi-html border m-1 p-4'><span>#{subbed_content}</span></div>"
|
20
|
+
end
|
21
|
+
|
22
|
+
def render_raw?
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :subject
|
29
|
+
|
30
|
+
def subbed_content
|
31
|
+
COLOR_CODES.reduce(subbed_hex_codes) do |string, color_code|
|
32
|
+
string&.gsub("\e[3#{color_code}m", "</span><span class='ansi-color-#{color_code}'>")
|
33
|
+
&.gsub("\e[9#{color_code}m", "</span><span class='ansi-bright ansi-color-#{color_code}'>")
|
34
|
+
&.gsub(/\e\[38;5;([0-9]{1,3})m/, "</span><span class='ansi-color-\\1'>")
|
35
|
+
&.gsub("\e[0m", "</span><span class='ansi-color-reset'>")
|
36
|
+
end&.gsub(/\e\[[0-9;]+m/, '')
|
37
|
+
end
|
38
|
+
|
39
|
+
def subbed_hex_codes
|
40
|
+
subject&.gsub(/\e\[38;2;([0-9]+);([0-9]+);([0-9]+)m/, '</span><span style="color: rgb(\1,\2,\3)">')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpecDocumentation
|
4
|
+
module Formatters
|
5
|
+
# Beautifies HTML received from a `subject`, renders the raw subject to be inserted directly
|
6
|
+
# into the output document.
|
7
|
+
class Html
|
8
|
+
def initialize(subject:)
|
9
|
+
@subject = subject
|
10
|
+
end
|
11
|
+
|
12
|
+
def prettified_output
|
13
|
+
formatter = Rouge::Formatters::HTML.new
|
14
|
+
lexer = Rouge::Lexers::HTML.new
|
15
|
+
formatter.format(lexer.lex(HtmlBeautifier.beautify(subject)))
|
16
|
+
end
|
17
|
+
|
18
|
+
def rendered_output
|
19
|
+
subject
|
20
|
+
end
|
21
|
+
|
22
|
+
def render_raw?
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :subject
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpecDocumentation
|
4
|
+
module Formatters
|
5
|
+
# Produces prettified JSON to from an RSpec `subject` value.
|
6
|
+
class Json
|
7
|
+
def initialize(subject:)
|
8
|
+
@subject = subject
|
9
|
+
end
|
10
|
+
|
11
|
+
def prettified_output
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def rendered_output
|
16
|
+
formatter = Rouge::Formatters::HTML.new
|
17
|
+
lexer = Rouge::Lexers::JSON.new
|
18
|
+
formatter.format(lexer.lex(JSON.pretty_generate(JSON.parse(subject))))
|
19
|
+
rescue JSON::ParserError => e
|
20
|
+
raise Error, "Expected JSON for:\n#{subject}\n\nParser Error: #{e}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def render_raw?
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :subject
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpecDocumentation
|
4
|
+
module Formatters
|
5
|
+
# Default formatter for all RSpec examples. Used by all examples to generate the "Spec" tab
|
6
|
+
# content, i.e. the original source of the example code.
|
7
|
+
class Ruby
|
8
|
+
def initialize(subject:)
|
9
|
+
@subject = subject
|
10
|
+
end
|
11
|
+
|
12
|
+
def prettified_output
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def rendered_output
|
17
|
+
formatter = Rouge::Formatters::HTML.new
|
18
|
+
lexer = Rouge::Lexers::Ruby.new
|
19
|
+
formatter.format(lexer.lex(subject.inspect))
|
20
|
+
end
|
21
|
+
|
22
|
+
def render_raw?
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :subject
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpecDocumentation
|
4
|
+
module Formatters
|
5
|
+
# Produces prettified YAML to from an RSpec `subject` value.
|
6
|
+
class Yaml
|
7
|
+
def initialize(subject:)
|
8
|
+
@subject = subject
|
9
|
+
end
|
10
|
+
|
11
|
+
def prettified_output
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def rendered_output
|
16
|
+
formatter = Rouge::Formatters::HTML.new
|
17
|
+
lexer = Rouge::Lexers::YAML.new
|
18
|
+
formatter.format(lexer.lex(YAML.safe_load(subject, permitted_classes: permitted_classes).to_yaml))
|
19
|
+
rescue Psych::SyntaxError => e
|
20
|
+
raise Error, "Expected YAML for:\n#{subject}\n\nSyntax Error: #{e}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def render_raw?
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :subject
|
30
|
+
|
31
|
+
def permitted_classes
|
32
|
+
[Symbol, Date, Time, DateTime]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'formatters/ruby'
|
4
|
+
require_relative 'formatters/html'
|
5
|
+
require_relative 'formatters/ansi'
|
6
|
+
require_relative 'formatters/json'
|
7
|
+
require_relative 'formatters/yaml'
|
8
|
+
|
9
|
+
module RSpecDocumentation
|
10
|
+
# Provides a set of formatters for rendering the value of a `subject` in an RSpec example into
|
11
|
+
# a useful format according to the language specified in the relevant Markdown code block, e.g.
|
12
|
+
# `rspec:html` will use the `Html` formatter to render beautified HTML source and the rendered
|
13
|
+
# output.
|
14
|
+
module Formatters
|
15
|
+
def self.with_translated_html_entities(content)
|
16
|
+
content&.gsub("\n", '<br/>')
|
17
|
+
&.gsub(' ', ' ')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -14,24 +14,24 @@ module RSpecDocumentation
|
|
14
14
|
Kramdown::Document.new(tabbed_spec, input: 'html').root
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
return nil unless spec.format == :html
|
19
|
-
|
17
|
+
def code_source
|
20
18
|
formatter = Rouge::Formatters::HTML.new
|
21
|
-
lexer = Rouge::Lexers::
|
22
|
-
|
23
|
-
formatter.format(lexer.lex(HtmlBeautifier.beautify(spec.described_object)))
|
19
|
+
lexer = Rouge::Lexers::Ruby.new
|
20
|
+
Formatters.with_translated_html_entities(formatter.format(lexer.lex(spec.source)))
|
24
21
|
end
|
25
22
|
|
26
|
-
def
|
27
|
-
|
23
|
+
def prettified_output
|
24
|
+
Formatters.with_translated_html_entities(formatter.prettified_output)
|
28
25
|
end
|
29
26
|
|
30
|
-
def
|
31
|
-
return
|
32
|
-
|
27
|
+
def rendered_output
|
28
|
+
return formatter.rendered_output if render_raw?
|
29
|
+
|
30
|
+
Formatters.with_translated_html_entities(formatter.rendered_output)
|
31
|
+
end
|
33
32
|
|
34
|
-
|
33
|
+
def render_raw?
|
34
|
+
formatter.render_raw?
|
35
35
|
end
|
36
36
|
|
37
37
|
def element_id
|
@@ -42,14 +42,17 @@ module RSpecDocumentation
|
|
42
42
|
|
43
43
|
attr_reader :spec
|
44
44
|
|
45
|
-
def
|
46
|
-
|
45
|
+
def formatter
|
46
|
+
@formatter ||= {
|
47
|
+
html: Formatters::Html,
|
48
|
+
ansi: Formatters::Ansi,
|
49
|
+
json: Formatters::Json,
|
50
|
+
yaml: Formatters::Yaml
|
51
|
+
}.fetch(spec.format, Formatters::Ruby).new(subject: spec.subject)
|
47
52
|
end
|
48
53
|
|
49
|
-
def
|
50
|
-
|
51
|
-
lexer = Rouge::Lexers::Ruby.new
|
52
|
-
formatter.format(lexer.lex(code))
|
54
|
+
def tabbed_spec
|
55
|
+
RSpecDocumentation.template('tabbed_spec').result(binding)
|
53
56
|
end
|
54
57
|
end
|
55
58
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpecDocumentation
|
4
|
+
# Compiles Javascript assets into a single file.
|
5
|
+
class JavascriptBundle
|
6
|
+
def flush
|
7
|
+
Util.bundle_dir.join('assets').mkpath
|
8
|
+
javascript_bundle_path.write(RSpecDocumentation.template(:layout, :js).result(binding))
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def javascript_bundle_path
|
14
|
+
Util.bundle_dir.join('assets/bundle.js')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|