rspec-documentation 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/.rubocop.yml +3 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +25 -2
  6. data/Makefile +9 -0
  7. data/README.md +18 -22
  8. data/Rakefile +1 -0
  9. data/exe/rspec-documentation +17 -0
  10. data/lib/rspec/documentation/version.rb +2 -2
  11. data/lib/rspec/documentation.rb +15 -2
  12. data/lib/rspec_documentation/configuration.rb +28 -0
  13. data/lib/rspec_documentation/document.rb +75 -0
  14. data/lib/rspec_documentation/documentation.rb +85 -0
  15. data/lib/rspec_documentation/formatters/ansi.rb +44 -0
  16. data/lib/rspec_documentation/formatters/html.rb +31 -0
  17. data/lib/rspec_documentation/formatters/json.rb +32 -0
  18. data/lib/rspec_documentation/formatters/ruby.rb +31 -0
  19. data/lib/rspec_documentation/formatters/yaml.rb +36 -0
  20. data/lib/rspec_documentation/formatters.rb +20 -0
  21. data/lib/rspec_documentation/html_element.rb +58 -0
  22. data/lib/rspec_documentation/javascript_bundle.rb +17 -0
  23. data/lib/rspec_documentation/markdown_renderer.rb +7 -0
  24. data/lib/rspec_documentation/page_collection.rb +64 -0
  25. data/lib/rspec_documentation/page_tree.rb +81 -0
  26. data/lib/rspec_documentation/page_tree_element.rb +78 -0
  27. data/lib/rspec_documentation/parsed_document.rb +72 -0
  28. data/lib/rspec_documentation/project_initialization.rb +52 -0
  29. data/lib/rspec_documentation/rspec/failure.rb +52 -0
  30. data/lib/rspec_documentation/rspec.rb +12 -0
  31. data/lib/rspec_documentation/spec.rb +108 -0
  32. data/lib/rspec_documentation/stylesheet_bundle.rb +17 -0
  33. data/lib/rspec_documentation/summary.rb +87 -0
  34. data/lib/rspec_documentation/util.rb +58 -0
  35. data/lib/rspec_documentation.rb +71 -0
  36. data/lib/tasks/rspec/documentation/generate.rake +10 -0
  37. data/lib/templates/000-Introduction.md.erb +35 -0
  38. data/lib/templates/010-Usage.md.erb +3 -0
  39. data/lib/templates/500-License.md.erb +3 -0
  40. data/lib/templates/bootstrap.js.erb +7 -0
  41. data/lib/templates/footer.html.erb +6 -0
  42. data/lib/templates/header.html.erb +20 -0
  43. data/lib/templates/layout.css.erb +418 -0
  44. data/lib/templates/layout.html.erb +31 -0
  45. data/lib/templates/layout.js.erb +67 -0
  46. data/lib/templates/modal_spec.html.erb +51 -0
  47. data/lib/templates/moon.svg.erb +1 -0
  48. data/lib/templates/script_tags.html.erb +1 -0
  49. data/lib/templates/stylesheet_links.html.erb +1 -0
  50. data/lib/templates/sun.svg.erb +1 -0
  51. data/lib/templates/tabbed_spec.html.erb +82 -0
  52. data/lib/templates/themes/bootstrap.min.css +11 -0
  53. data/lib/templates/themes/cerulean.css +11 -0
  54. data/lib/templates/themes/cosmo.css +11 -0
  55. data/lib/templates/themes/cyborg.css +11 -0
  56. data/lib/templates/themes/darkly.css +11 -0
  57. data/lib/templates/themes/flatly.css +11 -0
  58. data/lib/templates/themes/journal.css +11 -0
  59. data/lib/templates/themes/litera.css +11 -0
  60. data/lib/templates/themes/lumen.css +11 -0
  61. data/lib/templates/themes/lux.css +11 -0
  62. data/lib/templates/themes/materia.css +11 -0
  63. data/lib/templates/themes/minty.css +11 -0
  64. data/lib/templates/themes/morph.css +11 -0
  65. data/lib/templates/themes/pulse.css +11 -0
  66. data/lib/templates/themes/quartz.css +11 -0
  67. data/lib/templates/themes/sandstone.css +11 -0
  68. data/lib/templates/themes/simplex.css +11 -0
  69. data/lib/templates/themes/sketchy.css +11 -0
  70. data/lib/templates/themes/slate.css +11 -0
  71. data/lib/templates/themes/solar.css +11 -0
  72. data/lib/templates/themes/spacelab.css +11 -0
  73. data/lib/templates/themes/superhero.css +11 -0
  74. data/lib/templates/themes/united.css +11 -0
  75. data/lib/templates/themes/vapor.css +11 -0
  76. data/lib/templates/themes/yeti.css +11 -0
  77. data/lib/templates/themes/zephyr.css +11 -0
  78. data/rspec-documentation/pages/000-Introduction/000-Quickstart.md +17 -0
  79. data/rspec-documentation/pages/000-Introduction.md +23 -0
  80. data/rspec-documentation/pages/010-File System/000-Ordering.md +14 -0
  81. data/rspec-documentation/pages/010-File System/010-Documentation Bundle.md +9 -0
  82. data/rspec-documentation/pages/010-File System.md +26 -0
  83. data/rspec-documentation/pages/020-Running Tests.md +41 -0
  84. data/rspec-documentation/pages/030-Examples/010-Basic.md +51 -0
  85. data/rspec-documentation/pages/030-Examples/020-HTML.md +45 -0
  86. data/rspec-documentation/pages/030-Examples/030-ANSI.md +33 -0
  87. data/rspec-documentation/pages/030-Examples/040-JSON.md +39 -0
  88. data/rspec-documentation/pages/030-Examples/050-YAML.md +40 -0
  89. data/rspec-documentation/pages/030-Examples.md +7 -0
  90. data/rspec-documentation/pages/040-Spec Helper.md +11 -0
  91. data/rspec-documentation/pages/050-Linking.md +20 -0
  92. data/rspec-documentation/pages/060-Configuration/010-Context.md +26 -0
  93. data/rspec-documentation/pages/060-Configuration/020-Build Paths.md +33 -0
  94. data/rspec-documentation/pages/060-Configuration/030-Attribution.md +23 -0
  95. data/rspec-documentation/pages/060-Configuration.md +13 -0
  96. data/rspec-documentation/pages/070-Publishing.md +13 -0
  97. data/rspec-documentation/pages/500-License.md +11 -0
  98. data/rspec-documentation/spec_helper.rb +8 -0
  99. data/rspec-documentation.gemspec +10 -1
  100. data/sig/rspec/documentation.rbs +1 -1
  101. metadata +193 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31073f998af7b0e0f74ebd590721dc9ba5c4aa73b9ed88bf6848a77c189d7355
4
- data.tar.gz: 83343ddbbd95d4e100b2675a7e72a92c5ca9df225e99454308bd2af2b078b7ae
3
+ metadata.gz: a964ddab12c98c8913f741374a4206eaff591787f10e692417d9cf097fd2fe45
4
+ data.tar.gz: 5dd25967d474700f60118b12649906f072bf912a173651bcf5ea1e70889c7ecb
5
5
  SHA512:
6
- metadata.gz: e5d845f98a5ceaa7c0c6462cad990a598d84086955f61334b3011c5f3fb15d0e90cd1ba8fff75f3d1559aa8e8f841f78c16391e37a3c048bd1876916b0b352af
7
- data.tar.gz: '04739b7fb732fc7a1a6492f23d12d31d598b21d769c89238d0b29aa535a1620069fbc0b1610c8d1fa3d6a29a85a8d614768167b750c3416bbe83871f8990c11b'
6
+ metadata.gz: 1923b974e68f71be19dfeddc8379d242c54c3ce69770490399237897d46672177c15fa4990260bef4442414746e273e2e1f0764b67ac134a28c4d2c0a2336b09
7
+ data.tar.gz: 5f25067b064fa2acca91e6b82a45d1bf5218005885262b638589b0a94b746daf9c2c7da21b34b64865cec1e3d924c5f960adc30505c5ced25a146059c4a10bd6
data/.rspec CHANGED
@@ -1,3 +1,4 @@
1
1
  --format documentation
2
2
  --color
3
3
  --require spec_helper
4
+ --exclude spec/fixtures/**/*_spec.rb
data/.rubocop.yml CHANGED
@@ -4,3 +4,6 @@ require:
4
4
 
5
5
  AllCops:
6
6
  NewCops: enable
7
+ Exclude:
8
+ - 'spec/fixtures/**/*'
9
+ - 'lib/rspec_documentation/page_tree.rb' # Rubocop bug, fixed in main
data/Gemfile CHANGED
@@ -7,7 +7,10 @@ gemspec
7
7
 
8
8
  gem 'rake', '~> 13.0'
9
9
 
10
+ gem 'devpack', '~> 0.4.1'
10
11
  gem 'rspec', '~> 3.0'
12
+ gem 'rspec-file_fixtures', '~> 0.1.6'
13
+ gem 'rspec-its', '~> 1.3'
11
14
  gem 'rubocop', '~> 1.51'
12
15
  gem 'rubocop-rake', '~> 0.6.0'
13
16
  gem 'rubocop-rspec', '~> 2.22'
data/Gemfile.lock CHANGED
@@ -1,25 +1,41 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rspec-documentation (0.0.1)
4
+ rspec-documentation (0.0.3)
5
+ htmlbeautifier (~> 1.4)
6
+ kramdown (~> 2.4)
7
+ kramdown-parser-gfm (~> 1.1)
8
+ paintbrush (~> 0.1.3)
9
+ redcarpet (~> 3.6)
10
+ rouge (~> 4.1)
11
+ rspec (~> 3.12)
5
12
 
6
13
  GEM
7
14
  remote: https://rubygems.org/
8
15
  specs:
9
16
  ast (2.4.2)
10
17
  concurrent-ruby (1.2.2)
18
+ devpack (0.4.1)
11
19
  diff-lcs (1.5.0)
20
+ htmlbeautifier (1.4.2)
12
21
  i18n (1.13.0)
13
22
  concurrent-ruby (~> 1.0)
14
23
  json (2.6.3)
24
+ kramdown (2.4.0)
25
+ rexml
26
+ kramdown-parser-gfm (1.1.0)
27
+ kramdown (~> 2.0)
15
28
  paint (2.3.0)
29
+ paintbrush (0.1.3)
16
30
  parallel (1.23.0)
17
31
  parser (3.2.2.1)
18
32
  ast (~> 2.4.1)
19
33
  rainbow (3.1.1)
20
34
  rake (13.0.6)
35
+ redcarpet (3.6.0)
21
36
  regexp_parser (2.8.0)
22
37
  rexml (3.2.5)
38
+ rouge (4.1.1)
23
39
  rspec (3.12.0)
24
40
  rspec-core (~> 3.12.0)
25
41
  rspec-expectations (~> 3.12.0)
@@ -29,6 +45,11 @@ GEM
29
45
  rspec-expectations (3.12.3)
30
46
  diff-lcs (>= 1.2.0, < 2.0)
31
47
  rspec-support (~> 3.12.0)
48
+ rspec-file_fixtures (0.1.6)
49
+ rspec (~> 3.0)
50
+ rspec-its (1.3.0)
51
+ rspec-core (>= 3.0.0)
52
+ rspec-expectations (>= 3.0.0)
32
53
  rspec-mocks (3.12.5)
33
54
  diff-lcs (>= 1.2.0, < 2.0)
34
55
  rspec-support (~> 3.12.0)
@@ -62,13 +83,15 @@ GEM
62
83
  unicode-display_width (2.4.2)
63
84
 
64
85
  PLATFORMS
65
- ruby
66
86
  x86_64-linux
67
87
 
68
88
  DEPENDENCIES
89
+ devpack (~> 0.4.1)
69
90
  rake (~> 13.0)
70
91
  rspec (~> 3.0)
71
92
  rspec-documentation!
93
+ rspec-file_fixtures (~> 0.1.6)
94
+ rspec-its (~> 1.3)
72
95
  rubocop (~> 1.51)
73
96
  rubocop-rake (~> 0.6.0)
74
97
  rubocop-rspec (~> 2.22)
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
- # Rspec::Documentation
1
+ # RSpec::Documentation
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
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
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/rspec/documentation`. To experiment with that code, run `bin/console` for an interactive prompt.
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
- ## Installation
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
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
12
+ ## Quick Example
10
13
 
11
- Install the gem and add to the application's Gemfile by executing:
14
+ The following is an example _Markdown_ file.
12
15
 
13
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
16
+ ````console
17
+ # An example test
14
18
 
15
- If bundler is not being used to manage dependencies, install the gem by executing:
19
+ This is a very simple test:
16
20
 
17
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
21
+ ```rspec
22
+ subject { 'my subject' }
23
+ it { is_expected.to eql 'my subject' }
24
+ ```
25
+ ````
18
26
 
19
- ## Usage
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/Rakefile CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'bundler/gem_tasks'
4
4
  require 'rspec/core/rake_task'
5
+ require 'rspec/documentation'
5
6
 
6
7
  RSpec::Core::RakeTask.new(:spec)
7
8
 
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/rspec/documentation'
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
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Rspec
3
+ module RSpec
4
4
  module Documentation
5
- VERSION = '0.0.1'
5
+ VERSION = '0.0.3'
6
6
  end
7
7
  end
@@ -1,10 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'documentation/version'
4
+ require_relative '../rspec_documentation'
5
+ load File.expand_path(File.join(__dir__, '../tasks/rspec/documentation/generate.rake'))
4
6
 
5
- module Rspec
7
+ module RSpec
8
+ # Extension for RSpec, locates RSpec examples found in a Markdown file and executes them,
9
+ # replacing their output into a tree of Markdown files.
6
10
  module Documentation
7
11
  class Error < StandardError; end
8
- # Your code goes here...
12
+
13
+ class << self
14
+ def generate_documentation
15
+ RSpecDocumentation::Documentation.new.tap(&:generate)
16
+ end
17
+
18
+ def configure(&block)
19
+ RSpecDocumentation.configure(&block)
20
+ end
21
+ end
9
22
  end
10
23
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpecDocumentation
4
+ # Configures the rspec-documentation gem, allows setting a context that makes values available to each example.
5
+ class Configuration
6
+ def initialize
7
+ @context_defined = false
8
+ end
9
+
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)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpecDocumentation
4
+ # Translates a Markdown document into a structure of parsed Markdown and embedded RSpec examples.
5
+ class Document
6
+ attr_reader :failures, :page_tree
7
+
8
+ def initialize(document:, path:, page_tree:)
9
+ @document = document
10
+ @path = path
11
+ @page_tree = page_tree
12
+ @failures = []
13
+ end
14
+
15
+ def specs
16
+ @specs ||= parsed_document.specs
17
+ end
18
+
19
+ def render
20
+ parsed_document.execute_and_substitute_examples!
21
+ if parsed_document.failures.empty?
22
+ RSpecDocumentation.template('layout').result(binding)
23
+ else
24
+ failures.concat(parsed_document.failures)
25
+ nil
26
+ end
27
+ end
28
+
29
+ def html
30
+ parsed_document.html
31
+ end
32
+
33
+ def title
34
+ return ::Rails.application.class.module_parent.name.titleize if defined?(::Rails)
35
+
36
+ gem_spec&.name
37
+ end
38
+
39
+ def version
40
+ gem_spec&.version
41
+ end
42
+
43
+ def homepage
44
+ gem_spec&.homepage
45
+ end
46
+
47
+ def header
48
+ RSpecDocumentation.template('header').result(binding)
49
+ end
50
+
51
+ def footer
52
+ RSpecDocumentation.template('footer').result(binding)
53
+ end
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
+
63
+ private
64
+
65
+ attr_reader :document, :path
66
+
67
+ def parsed_document
68
+ @parsed_document ||= ParsedDocument.new(document, path: path)
69
+ end
70
+
71
+ def gem_spec
72
+ @gem_spec ||= Gem::Specification.load(Pathname.new(Dir.pwd).glob('*.gemspec').first.to_s)
73
+ end
74
+ end
75
+ end
@@ -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(' ', '&nbsp;&nbsp;')
18
+ end
19
+ end
20
+ end