rspec-documentation 0.0.7 → 0.0.8

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/Gemfile +1 -0
  4. data/Gemfile.lock +15 -10
  5. data/exe/rspec-documentation +15 -0
  6. data/lib/rspec/documentation/version.rb +1 -1
  7. data/lib/rspec_documentation/configuration.rb +5 -1
  8. data/lib/rspec_documentation/document.rb +8 -1
  9. data/lib/rspec_documentation/documentation.rb +5 -6
  10. data/lib/rspec_documentation/kramdown_html_converter.rb +13 -0
  11. data/lib/rspec_documentation/page_collection.rb +3 -0
  12. data/lib/rspec_documentation/page_tree.rb +7 -3
  13. data/lib/rspec_documentation/page_tree_element.rb +1 -1
  14. data/lib/rspec_documentation/parsed_document.rb +38 -4
  15. data/lib/rspec_documentation/project_initialization.rb +8 -0
  16. data/lib/rspec_documentation/rspec/failure.rb +1 -1
  17. data/lib/rspec_documentation/util.rb +12 -2
  18. data/lib/templates/layout.css.erb +106 -4
  19. data/lib/templates/layout.html.erb +13 -4
  20. data/lib/templates/layout.js.erb +86 -4
  21. data/lib/templates/link.svg.erb +1 -0
  22. data/lib/templates/modal_spec.html.erb +5 -5
  23. data/lib/templates/spec_helper.rb.erb +25 -0
  24. data/lib/templates/tabbed_spec.html.erb +4 -4
  25. data/rspec-documentation/pages/001-Quickstart.md +9 -1
  26. data/rspec-documentation/pages/020-Running Tests.md +6 -21
  27. data/rspec-documentation/pages/030-Examples/012-Regular it Blocks.md +7 -7
  28. data/rspec-documentation/pages/030-Examples/020-HTML.md +14 -14
  29. data/rspec-documentation/pages/030-Examples/030-ANSI.md +3 -3
  30. data/rspec-documentation/pages/030-Examples/040-JSON.md +4 -4
  31. data/rspec-documentation/pages/030-Examples/050-YAML.md +4 -4
  32. data/rspec-documentation/pages/030-Examples/060-XML.md +4 -4
  33. data/rspec-documentation/pages/060-Configuration/Index Search.md +13 -0
  34. data/rspec-documentation/pages/060-Configuration/Table of Contents.md +35 -0
  35. data/rspec-documentation/pages/080-Rubocop.md +36 -0
  36. data/rspec-documentation/spec_helper.rb +1 -0
  37. metadata +12 -7
  38. /data/rspec-documentation/pages/060-Configuration/{030-Attribution.md → Attribution.md} +0 -0
  39. /data/rspec-documentation/pages/060-Configuration/{020-Build Paths.md → Build Paths.md} +0 -0
  40. /data/rspec-documentation/pages/060-Configuration/{050-Consistent Height.md → Consistent Height.md} +0 -0
  41. /data/rspec-documentation/pages/060-Configuration/{010-Context.md → Context.md} +0 -0
  42. /data/rspec-documentation/pages/060-Configuration/{040-Hooks.md → Hooks.md} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da04d0bb8e452ebcf2858bff1c50b704099bd28ef683e4bd18759952195b8543
4
- data.tar.gz: db7bb967b2c35fd6b972f3ff295561e1731ade67d07c9d6132f797504d855cc3
3
+ metadata.gz: 8ce43727fba18b77d655b8ba4dc96b66b730823d4c44603a17d3033f70092daa
4
+ data.tar.gz: a53de33b4779cca033dfaa87eea7e60f473af09db986117c9a3d98cd9417d874
5
5
  SHA512:
6
- metadata.gz: 733742f420606fab2d6cb27ab9c180e2c30260184e903314337ae994453de0d3863e00df34407f613103d9bef55697fea044fde7e436018e50fdf39a68f41e02
7
- data.tar.gz: 4271936018c835d3e6af24d8a1f5329a3b229b89528d53e04cba2a44e42b459f49a4fde648820a9e1e9a0710fe692db891ecc866d5a5a9767f7ad9098c30f330
6
+ metadata.gz: 7e44facb6a2ece7170e6111ced783f9e4a48780f478afbd257c6f30552816f6fcb22ab6733914f26c68168a71331f77c777f770e0e343c0301ad2be23855602e
7
+ data.tar.gz: ac708a5ee5336cb2c2aa9282704a94bb0d6d1f8120293af0cbc84e63d3914d88de25fdff7b942a1759f8f7a8d17e8252398ed3ba06d771c77023fa206bb42bc1
data/.rubocop.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  require:
2
+ - 'rubocop-rspec-documentation'
2
3
  - 'rubocop-rake'
3
4
  - 'rubocop-rspec'
4
5
 
data/Gemfile CHANGED
@@ -15,4 +15,5 @@ gem 'rspec-its', '~> 1.3'
15
15
  gem 'rubocop', '~> 1.52'
16
16
  gem 'rubocop-rake', '~> 0.6.0'
17
17
  gem 'rubocop-rspec', '~> 2.22'
18
+ gem 'rubocop-rspec-documentation', require: false
18
19
  gem 'strong_versions', '~> 0.4.5'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rspec-documentation (0.0.7)
4
+ rspec-documentation (0.0.8)
5
5
  htmlbeautifier (~> 1.4)
6
6
  kramdown (~> 2.4)
7
7
  kramdown-parser-gfm (~> 1.1)
@@ -19,7 +19,7 @@ GEM
19
19
  devpack (0.4.1)
20
20
  diff-lcs (1.5.0)
21
21
  htmlbeautifier (1.4.2)
22
- i18n (1.13.0)
22
+ i18n (1.14.1)
23
23
  concurrent-ruby (~> 1.0)
24
24
  json (2.6.3)
25
25
  kramdown (2.4.0)
@@ -31,15 +31,16 @@ GEM
31
31
  paint (2.3.0)
32
32
  paintbrush (0.1.3)
33
33
  parallel (1.23.0)
34
- parser (3.2.2.1)
34
+ parser (3.2.2.3)
35
35
  ast (~> 2.4.1)
36
- racc (1.6.2)
36
+ racc
37
+ racc (1.7.0)
37
38
  rainbow (3.1.1)
38
39
  rake (13.0.6)
39
40
  redcarpet (3.6.0)
40
- regexp_parser (2.8.0)
41
+ regexp_parser (2.8.1)
41
42
  rexml (3.2.5)
42
- rouge (4.1.1)
43
+ rouge (4.1.2)
43
44
  rspec (3.12.0)
44
45
  rspec-core (~> 3.12.0)
45
46
  rspec-expectations (~> 3.12.0)
@@ -49,8 +50,8 @@ GEM
49
50
  rspec-expectations (3.12.3)
50
51
  diff-lcs (>= 1.2.0, < 2.0)
51
52
  rspec-support (~> 3.12.0)
52
- rspec-file_fixtures (0.1.6)
53
- rspec (~> 3.0)
53
+ rspec-file_fixtures (0.1.7)
54
+ rspec (~> 3.12)
54
55
  rspec-its (1.3.0)
55
56
  rspec-core (>= 3.0.0)
56
57
  rspec-expectations (>= 3.0.0)
@@ -58,10 +59,10 @@ GEM
58
59
  diff-lcs (>= 1.2.0, < 2.0)
59
60
  rspec-support (~> 3.12.0)
60
61
  rspec-support (3.12.0)
61
- rubocop (1.52.0)
62
+ rubocop (1.52.1)
62
63
  json (~> 2.3)
63
64
  parallel (~> 1.10)
64
- parser (>= 3.2.0.0)
65
+ parser (>= 3.2.2.3)
65
66
  rainbow (>= 2.2.2, < 4.0)
66
67
  regexp_parser (>= 1.8, < 3.0)
67
68
  rexml (>= 3.2.5, < 4.0)
@@ -80,6 +81,9 @@ GEM
80
81
  rubocop (~> 1.33)
81
82
  rubocop-capybara (~> 2.17)
82
83
  rubocop-factory_bot (~> 2.22)
84
+ rubocop-rspec-documentation (0.0.1)
85
+ rspec-documentation (~> 0.0.7)
86
+ rubocop (~> 1.52)
83
87
  ruby-progressbar (1.13.0)
84
88
  strong_versions (0.4.5)
85
89
  i18n (>= 0.5)
@@ -100,6 +104,7 @@ DEPENDENCIES
100
104
  rubocop (~> 1.52)
101
105
  rubocop-rake (~> 0.6.0)
102
106
  rubocop-rspec (~> 2.22)
107
+ rubocop-rspec-documentation
103
108
  strong_versions (~> 0.4.5)
104
109
 
105
110
  BUNDLED WITH
@@ -3,6 +3,21 @@
3
3
 
4
4
  require_relative '../lib/rspec/documentation'
5
5
 
6
+ require 'optparse'
7
+
8
+ options = {}
9
+
10
+ OptionParser.new do |opts|
11
+ opts.banner = 'Usage: rspec-documentation [options]'
12
+ opts.on('-F', '--fail-fast', 'Abort the run after the first failure.') { |val| options[:fail_fast] = val if val }
13
+ opts.on('-b', '--backtrace', 'Enable full backtrace.') { |val| options[:full_backtrace] = val if val }
14
+ end.parse!
15
+
16
+ RSpec::Documentation.configure do |config|
17
+ config.fail_fast = options[:fail_fast] if options.key?(:fail_fast)
18
+ config.full_backtrace = options[:full_backtrace] if options.key?(:full_backtrace)
19
+ end
20
+
6
21
  documentation = RSpec::Documentation.generate_documentation
7
22
 
8
23
  exit 1 if documentation.failed?
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RSpec
4
4
  module Documentation
5
- VERSION = '0.0.7'
5
+ VERSION = '0.0.8'
6
6
  end
7
7
  end
@@ -4,12 +4,16 @@ 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
  attr_reader :hooks
7
- attr_accessor :consistent_height, :max_height
7
+ attr_accessor :consistent_height, :max_height, :fail_fast, :full_backtrace, :table_of_contents, :index_search
8
8
 
9
9
  def initialize
10
10
  @context_defined = false
11
11
  @consistent_height = false
12
12
  @max_height = '30rem'
13
+ @fail_fast = false
14
+ @full_backtrace = false
15
+ @table_of_contents = true
16
+ @index_search = true
13
17
  @hooks = {}
14
18
  end
15
19
 
@@ -18,6 +18,7 @@ module RSpecDocumentation
18
18
 
19
19
  def render
20
20
  parsed_document.execute_and_substitute_examples!
21
+
21
22
  if parsed_document.failures.empty?
22
23
  RSpecDocumentation.template('layout').result(binding)
23
24
  else
@@ -63,11 +64,17 @@ module RSpecDocumentation
63
64
  attr_reader :document, :path
64
65
 
65
66
  def parsed_document
66
- @parsed_document ||= ParsedDocument.new(document, path: path)
67
+ @parsed_document ||= ParsedDocument.new(with_table_of_contents(document), path: path)
67
68
  end
68
69
 
69
70
  def gem_spec
70
71
  @gem_spec ||= Gem::Specification.load(Pathname.new(Dir.pwd).glob('*.gemspec').first.to_s)
71
72
  end
73
+
74
+ def with_table_of_contents(markdown)
75
+ return markdown unless RSpecDocumentation.configuration.table_of_contents
76
+
77
+ ['* TOC', '{:toc}', markdown].join("\n")
78
+ end
72
79
  end
73
80
  end
@@ -22,11 +22,14 @@ module RSpecDocumentation
22
22
  @failed || !page_collection.failures.empty?
23
23
  end
24
24
 
25
+ def page_collection
26
+ @page_collection ||= RSpecDocumentation::PageCollection.new(page_paths: page_paths)
27
+ end
28
+
25
29
  private
26
30
 
27
31
  def require_spec_helper
28
- path = pwd.join('rspec-documentation/spec_helper.rb')
29
- require path if path.file?
32
+ require Util.spec_helper_path if Util.spec_helper_path.file?
30
33
  end
31
34
 
32
35
  # Ensure `__rspec_documentation` shared context is always defined.
@@ -74,10 +77,6 @@ module RSpecDocumentation
74
77
  @page_paths ||= pwd.join('rspec-documentation/pages').glob('**/*.md')
75
78
  end
76
79
 
77
- def page_collection
78
- @page_collection ||= RSpecDocumentation::PageCollection.new(page_paths: page_paths)
79
- end
80
-
81
80
  def pwd
82
81
  @pwd ||= Pathname.new(Dir.pwd)
83
82
  end
@@ -9,6 +9,19 @@ module Kramdown
9
9
  element.attr['class'] ||= 'rspec-documentation-table table'
10
10
  super
11
11
  end
12
+
13
+ def convert_header(element, indent)
14
+ [
15
+ '<div class="heading">',
16
+ super,
17
+ "<a class='heading-anchor' href='##{element.attr['id']}'>#{link_icon}</a>",
18
+ '</div>'
19
+ ].join
20
+ end
21
+
22
+ def link_icon
23
+ @link_icon ||= RSpecDocumentation.template(:link, :svg).result
24
+ end
12
25
  end
13
26
  end
14
27
  end
@@ -6,6 +6,8 @@ module RSpecDocumentation
6
6
  class PageCollection
7
7
  attr_reader :failures, :page_paths
8
8
 
9
+ include Paintbrush
10
+
9
11
  def initialize(page_paths:)
10
12
  @page_paths = page_paths.sort_by(&:to_s)
11
13
  @buffer = {}
@@ -16,6 +18,7 @@ module RSpecDocumentation
16
18
  page_paths.zip(documents).each do |path, document|
17
19
  buffer[bundle_path_for(path)] = document.render
18
20
  failures.concat(document.failures)
21
+ break if RSpecDocumentation.configuration.fail_fast && !failures.empty?
19
22
  end
20
23
  end
21
24
 
@@ -48,15 +48,15 @@ module RSpecDocumentation
48
48
  nodes.last == '<ol>' ? nodes.pop : nodes.push('</ol>')
49
49
  end
50
50
 
51
- def build_tree(branch: structure, depth: 0)
52
- normalized_paths.each do |path|
51
+ def build_tree(paths: normalized_paths, branch: structure, depth: 0)
52
+ paths.each do |path|
53
53
  first, second, *rest = path_segments(path: path, depth: depth)
54
54
  next if second.nil?
55
55
 
56
56
  branch[first] ||= {}
57
57
  branch[first][:children] ||= Set.new
58
58
  branch[first][:children].add(second)
59
- build_tree(branch: branch[first], depth: depth + 1)
59
+ build_tree(paths: filtered_paths(path), branch: branch[first], depth: depth + 1)
60
60
  end
61
61
  end
62
62
 
@@ -74,6 +74,10 @@ module RSpecDocumentation
74
74
  end
75
75
  end
76
76
 
77
+ def filtered_paths(path)
78
+ normalized_paths.select { |normalized_path| normalized_path.to_s.start_with?(path.sub_ext('').to_s) }
79
+ end
80
+
77
81
  def page_tree_node(path:, child:)
78
82
  PageTreeElement.new(path: path, child: child, current_path: current_path).node
79
83
  end
@@ -44,7 +44,7 @@ module RSpecDocumentation
44
44
 
45
45
  def li_open
46
46
  "<li id='#{Util.path_id(path.join(child))}' #{active_class} data-list-item-id='##{path_id}' " \
47
- "data-parent-id='##{parent_path_id}'>"
47
+ "data-search-tokens='#{Util.tokens(child).to_json}' data-parent-id='##{parent_path_id}'>"
48
48
  end
49
49
 
50
50
  def link
@@ -5,8 +5,16 @@ module RSpecDocumentation
5
5
  class ParsedDocument
6
6
  attr_reader :failures
7
7
 
8
+ include Paintbrush
9
+
8
10
  def initialize(document, path:)
9
- @document = Kramdown::Document.new(document, input: 'GFM', syntax_highlighter: 'rouge')
11
+ @document = Kramdown::Document.new(
12
+ document,
13
+ toc_levels: 2...6,
14
+ input: 'GFM',
15
+ syntax_highlighter: 'rouge',
16
+ auto_ids: true
17
+ )
10
18
  @path = path
11
19
  @failures = []
12
20
  end
@@ -16,11 +24,11 @@ module RSpecDocumentation
16
24
  end
17
25
 
18
26
  def execute_and_substitute_examples!
27
+ print_empty if specs.empty?
19
28
  specs.each do |spec|
20
29
  spec.run
21
- next failures << spec.failure unless spec.failure.nil?
22
-
23
- spec.parent.children[spec.index] = spec_element(spec)
30
+ process_outcome(spec)
31
+ break if RSpecDocumentation.configuration.fail_fast && !failures.empty?
24
32
  end
25
33
  end
26
34
 
@@ -65,8 +73,34 @@ module RSpecDocumentation
65
73
  end
66
74
  end
67
75
 
76
+ def process_outcome(spec)
77
+ if spec.failure.nil?
78
+ print_success(spec)
79
+ spec.parent.children[spec.index] = spec_element(spec)
80
+ else
81
+ print_failure(spec)
82
+ failures << spec.failure
83
+ end
84
+ end
85
+
86
+ def relative_path
87
+ path.relative_path_from(Util.base_dir)
88
+ end
89
+
68
90
  def report_error(spec)
69
91
  $stderr.write(spec.failure.message)
70
92
  end
93
+
94
+ def print_empty
95
+ warn(paintbrush { cyan " #{relative_path}" })
96
+ end
97
+
98
+ def print_success(spec)
99
+ warn(paintbrush { green " #{relative_path}:#{spec.location}" })
100
+ end
101
+
102
+ def print_failure(spec)
103
+ warn(paintbrush { red " #{relative_path}:#{spec.location}" })
104
+ end
71
105
  end
72
106
  end
@@ -9,6 +9,7 @@ module RSpecDocumentation
9
9
  print_welcome
10
10
  create_base_dir
11
11
  create_sample_files
12
+ create_spec_helper
12
13
  print_initialization_complete
13
14
  end
14
15
 
@@ -31,6 +32,13 @@ module RSpecDocumentation
31
32
  end
32
33
  end
33
34
 
35
+ def create_spec_helper
36
+ return if Util.spec_helper_path.exist?
37
+
38
+ Util.spec_helper_path.write(RSpecDocumentation.template(:spec_helper, :rb).result)
39
+ print_created(Util.spec_helper_path)
40
+ end
41
+
34
42
  def print_created(path)
35
43
  warn(paintbrush { " #{green_b 'create'} #{cyan path.relative_path_from(pwd)}" })
36
44
  end
@@ -39,7 +39,7 @@ module RSpecDocumentation
39
39
 
40
40
  def formatted_backtrace
41
41
  cause.backtrace
42
- &.take_while { |line| line.start_with?(Dir.pwd) }
42
+ &.take_while { |line| RSpecDocumentation.configuration.full_backtrace || line.start_with?(Dir.pwd) }
43
43
  &.map { |line| paintbrush { red " #{line.sub("#{Dir.pwd}/", '')}" } }
44
44
  &.join("\n")
45
45
  end
@@ -14,6 +14,10 @@ module RSpecDocumentation
14
14
  bundle_dir.join('index.html')
15
15
  end
16
16
 
17
+ def self.spec_helper_path
18
+ root_dir.join('rspec-documentation/spec_helper.rb')
19
+ end
20
+
17
21
  def self.base_dir
18
22
  root_dir.join('rspec-documentation', 'pages')
19
23
  end
@@ -29,7 +33,11 @@ module RSpecDocumentation
29
33
  end
30
34
 
31
35
  def self.label(path)
32
- Pathname.new(path).basename.sub_ext('').sub(ORDERING_PREFIX_REGEXP, '')
36
+ Pathname.new(path).basename.sub_ext('').sub(ORDERING_PREFIX_REGEXP, '').to_s
37
+ end
38
+
39
+ def self.tokens(path)
40
+ label(path).downcase.split
33
41
  end
34
42
 
35
43
  def self.path_id(path)
@@ -52,7 +60,9 @@ module RSpecDocumentation
52
60
  end
53
61
 
54
62
  def self.normalized_filename(path)
55
- path.to_s.gsub(' ', '-').downcase.sub(ORDERING_PREFIX_REGEXP, '')
63
+ path.split.map do |segment|
64
+ segment.to_s.gsub(' ', '-').downcase.sub(ORDERING_PREFIX_REGEXP, '')
65
+ end.join('/')
56
66
  end
57
67
  end
58
68
  end
@@ -35,6 +35,35 @@
35
35
  }
36
36
  }
37
37
 
38
+ [data-bs-theme="dark"] .table-of-contents-wrapper {
39
+ border-color: #444242;
40
+ background-color: #4e4e4e55;
41
+ }
42
+
43
+ [data-bs-theme="dark"] .table-of-contents-wrapper .title {
44
+ border-color: #444242;
45
+ }
46
+
47
+ [data-bs-theme="dark"] table.rspec-documentation-table td, [data-bs-theme="dark"] table.rspec-documentation-table th {
48
+ border: 1px solid #4e4e4e;
49
+ }
50
+
51
+ [data-bs-theme="dark"] table.rspec-documentation-table tr:hover td {
52
+ background-color: #325d8833;
53
+ }
54
+
55
+ [data-bs-theme="dark"] .header-wrapper {
56
+ background-color: #212121;
57
+ }
58
+
59
+ [data-bs-theme="dark"] .form-control {
60
+ color: #b2b2b2;
61
+ }
62
+
63
+ [data-bs-theme="dark"] input.form-control::placeholder {
64
+ color: #999;
65
+ }
66
+
38
67
  body {
39
68
  opacity: 0;
40
69
  animation: fade-in ease-in 1;
@@ -45,6 +74,11 @@ body {
45
74
 
46
75
  .header-wrapper {
47
76
  background-color: #fff;
77
+ z-index: 100000;
78
+ }
79
+
80
+ table.rspec-documentation-table tr:hover td {
81
+ background-color: #8a8d9124;
48
82
  }
49
83
 
50
84
  table.rspec-documentation-table td, table.rspec-documentation-table th {
@@ -52,12 +86,68 @@ table.rspec-documentation-table td, table.rspec-documentation-table th {
52
86
  padding: 0.5rem 1rem;
53
87
  }
54
88
 
55
- [data-bs-theme="dark"] table.rspec-documentation-table td, [data-bs-theme="dark"] table.rspec-documentation-table th {
56
- border: 1px solid #4e4e4e;
89
+ .index-search {
90
+ margin-bottom: 1rem;
57
91
  }
58
92
 
59
- [data-bs-theme="dark"] .header-wrapper {
60
- background-color: #212121;
93
+ .page-tree li.search-active {
94
+ list-style: circle;
95
+ list-style-color: green;
96
+ }
97
+
98
+ .table-of-contents-wrapper {
99
+ position: relative;
100
+ padding: 0.4rem 0.8rem;
101
+ background-color: #c7c7c729;
102
+ display: inline-block;
103
+ float: right;
104
+ margin-left: 1rem;
105
+ margin-bottom: 0.4rem;
106
+ border-style: solid;
107
+ border-width: 1px;
108
+ border-radius: 10px;
109
+ border-color: #cfcfcf;
110
+ }
111
+
112
+ .table-of-contents-wrapper .title {
113
+ text-align: center;
114
+ border-bottom: 1px solid #cfcfcf;
115
+ margin-bottom: 0.2rem;
116
+ padding-bottom: 0.2rem;
117
+ font-weight: bold;
118
+ }
119
+
120
+ #markdown-toc {
121
+ list-style: disc;
122
+ line-height: 1.8rem;
123
+ padding: 0;
124
+ margin-bottom: 0;
125
+ padding-left: 1rem;
126
+ }
127
+
128
+ #markdown-toc ul {
129
+ padding-left: 1rem;
130
+ }
131
+
132
+ .heading-anchor {
133
+ padding: 0.2rem;
134
+ vertical-align: middle;
135
+ display: inline-block;
136
+ padding-bottom: 0.4rem;
137
+ scroll-padding-top: 5rem;
138
+ }
139
+
140
+ .heading-anchor svg {
141
+ width: 1rem;
142
+ height: 1rem;
143
+ }
144
+
145
+ .heading-anchor svg path {
146
+ fill: #7ac0f8;
147
+ }
148
+
149
+ #markdown-toc li a {
150
+ text-decoration: none;
61
151
  }
62
152
 
63
153
  .theme-switcher {
@@ -88,8 +178,20 @@ h1.title a {
88
178
  text-decoration: none;
89
179
  }
90
180
 
181
+ .content h1, .content h2, .content h3, .content h4, .content h5, .content h6 {
182
+ display: inline-block;
183
+ scroll-margin-top: 6rem;
184
+ }
185
+
186
+ .heading-anchor {
187
+ font-size: 0.8rem;
188
+ text-decoration: none;
189
+ color: rgb(122,192,248);
190
+ }
191
+
91
192
  .code {
92
193
  font-family: monospace;
194
+ font-size: 0.9rem;
93
195
  max-height: <%= RSpecDocumentation.configuration.max_height %>;
94
196
  overflow-y: auto;
95
197
  }
@@ -1,6 +1,7 @@
1
1
  <html>
2
2
  <head>
3
3
  <meta charset="utf-8" />
4
+ <title><%= title %></title>
4
5
  <%= RSpecDocumentation.template(:stylesheet_links).result(binding) %>
5
6
  <%= RSpecDocumentation.hook(:after_head) %>
6
7
  </head>
@@ -15,11 +16,19 @@
15
16
 
16
17
  <div class="row flex-nowrap">
17
18
  <div class="col-sm-2 fs-6 mt-1 ms-3 me-3">
18
- <ol class="page-tree hidden position-fixed">
19
- <% page_tree.elements.each do |element| %>
20
- <%= element %>
19
+ <div class="position-fixed">
20
+ <% if RSpecDocumentation.configuration.index_search %>
21
+ <div class="index-search">
22
+ <input type="text" class="index-search-field form-control" placeholder="Search (Ctrl+/)" />
23
+ </div>
21
24
  <% end %>
22
- </ol>
25
+
26
+ <ol class="page-tree hidden">
27
+ <% page_tree.elements.each do |element| %>
28
+ <%= element %>
29
+ <% end %>
30
+ </ol>
31
+ </div>
23
32
  </div>
24
33
 
25
34
  <%= RSpecDocumentation.hook(:before_content) %>
@@ -1,10 +1,11 @@
1
1
  <%= RSpecDocumentation.template('bootstrap', :js).result %>
2
2
 
3
3
  (() => {
4
- const initPageTree = () => {
5
- const pageTree = document.querySelector('.page-tree');
4
+ const pageTree = document.querySelector('.page-tree');
5
+ const getParentElement = (element) => document.querySelector(element.dataset.parentId);
6
+ const pageSearchTokens = {};
6
7
 
7
- const getParentElement = (element) => document.querySelector(element.dataset.parentId);
8
+ const initPageTree = () => {
8
9
  const isRootElement = (element) => !getParentElement(element);
9
10
  const isChildActive = (element) => !!element.querySelectorAll('.active').length;
10
11
  const isSiblingActive = (element) => !!getParentElement(element).querySelectorAll('.active').length;
@@ -22,7 +23,14 @@
22
23
  const visibilityCriteria = [isRootElement, isSelfOrParentActive, isChildActive, isSiblingActive];
23
24
 
24
25
  pageTree.querySelectorAll('li').forEach((element) => {
25
- if (!visibilityCriteria.some((criterion) => criterion(element))) element.classList.add('d-none');
26
+ element.classList.remove('search-active');
27
+ pageSearchTokens[element.id] = JSON.parse(element.dataset.searchTokens);
28
+
29
+ if (!visibilityCriteria.some((criterion) => criterion(element))) {
30
+ element.classList.add('d-none');
31
+ } else {
32
+ element.classList.remove('d-none');
33
+ }
26
34
  });
27
35
  pageTree.classList.remove('hidden');
28
36
  };
@@ -62,6 +70,80 @@
62
70
  });
63
71
  });
64
72
 
73
+ initTableOfContents = () => {
74
+ const tableOfContents = document.querySelector('#markdown-toc');
75
+
76
+ if (!tableOfContents) return;
77
+
78
+ const wrapper = document.createElement('div');
79
+ const content = document.querySelector('div.content');
80
+ const title = document.createElement('div');
81
+
82
+ title.append('Links');
83
+ title.classList.add('title');
84
+ wrapper.append(title);
85
+ wrapper.append(tableOfContents);
86
+ wrapper.classList.add('table-of-contents-wrapper');
87
+ content.prepend(wrapper);
88
+ };
89
+
90
+ initIndexSearch = () => {
91
+ const indexSearch = document.querySelector('.index-search');
92
+ const indexSearchField = indexSearch.querySelector('input');
93
+ const getQueryTokens = () => indexSearchField.value.toLowerCase().split(/\s+/);
94
+
95
+ indexSearch.addEventListener('keyup', (ev) => {
96
+ if (ev.keyCode === 13) {
97
+ const anchor = pageTree.querySelector('li.search-active a');
98
+ if (anchor) window.location = anchor.href;
99
+ } else {
100
+ searchIndex(getQueryTokens());
101
+ }
102
+ });
103
+ indexSearch.addEventListener('change', (ev) => searchIndex(getQueryTokens()));
104
+
105
+ document.addEventListener('keydown', (ev) => {
106
+ if (ev.ctrlKey && ev.keyCode === 191) {
107
+ ev.preventDefault();
108
+ indexSearchField.focus();
109
+ }
110
+ });
111
+
112
+ searchIndex = (searchTokens) => {
113
+ if (!searchTokens.every((searchToken) => searchToken)) {
114
+ initPageTree();
115
+ return;
116
+ }
117
+
118
+ const unhideRecursively = (element) => {
119
+ const parentElement = getParentElement(element);
120
+
121
+ element.classList.remove('d-none');
122
+
123
+ if (parentElement) unhideRecursively(parentElement);
124
+ };
125
+
126
+ const getMatchingTokens = (tokens) => {
127
+ const anyMatchingTokens = (token) => tokens.some((expectedToken) => expectedToken.includes(token))
128
+ return searchTokens.filter((token) => anyMatchingTokens(token));
129
+ };
130
+
131
+ pageTree.querySelectorAll('li').forEach((element) => {
132
+ const elementSearchTokens = pageSearchTokens[element.id];
133
+
134
+ if (getMatchingTokens(elementSearchTokens).length) {
135
+ element.classList.add('search-active');
136
+ unhideRecursively(element);
137
+ } else {
138
+ element.classList.add('d-none');
139
+ element.classList.remove('search-active');
140
+ }
141
+ });
142
+ };
143
+ };
144
+
65
145
  initPageTree();
66
146
  initThemeSwitcher();
147
+ initTableOfContents();
148
+ initIndexSearch();
67
149
  })();
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 122.88 122.88" style="enable-background:new 0 0 122.88 122.88" xml:space="preserve"><g><path d="M37.49,53.69c1.25-1.25,3.27-1.25,4.51,0c1.25,1.25,1.25,3.27,0,4.51L6.61,93.6l22.67,22.67l0,0l35.44-35.44 c1.25-1.25,3.27-1.25,4.51,0c1.25,1.25,1.25,3.27,0,4.52L33.4,121.18v0l-0.01-0.01l-0.01,0.01c-1.14,1.14-2.62,1.7-4.11,1.7 c-1.38,0-2.76-0.49-3.86-1.47c-0.09-0.07-0.17-0.15-0.26-0.23l0,0L1.7,97.72C0.57,96.58,0,95.09,0,93.6c0-1.49,0.57-2.98,1.7-4.12 L37.49,53.69L37.49,53.69z M77.12,41.24c1.25-1.25,3.27-1.25,4.52,0c1.25,1.25,1.25,3.27,0,4.52l-31.4,31.4 c-1.25,1.25-3.27,1.25-4.51,0c-1.25-1.25-1.25-3.27,0-4.51L77.12,41.24L77.12,41.24z M85.6,68.98c-1.25,1.25-3.27,1.25-4.52,0 c-1.25-1.25-1.25-3.27,0-4.52l35.19-35.19L93.6,6.61L58.48,41.73c-1.25,1.25-3.27,1.25-4.51,0c-1.25-1.25-1.25-3.27,0-4.51 L89.48,1.7C90.62,0.57,92.11,0,93.6,0c1.49,0,2.98,0.57,4.12,1.7l23.46,23.46l0,0l-0.01,0.01l0.01,0.01 c1.14,1.14,1.7,2.62,1.7,4.11c0,1.49-0.57,2.98-1.7,4.12l0,0L85.6,68.98L85.6,68.98z"/></g></svg>
@@ -2,14 +2,14 @@
2
2
  <div class="modal-dialog modal-xl" id="modal-dialog-<%= element_id %>">
3
3
  <div class="modal-content">
4
4
  <div class="modal-header">
5
- <h5 class="modal-title" id="modal-<%= element_id %>-side-by-side-label">Side-by-side view</h5>
5
+ <h5 class="no_toc modal-title" id="modal-<%= element_id %>-side-by-side-label">Side-by-side view</h5>
6
6
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
7
7
  </div>
8
8
  <div class="modal-body">
9
9
  <div class="container p-3">
10
10
  <div class="row border">
11
11
  <div class="col border">
12
- <h5>Spec</h5>
12
+ <h5 class="no_toc">Spec</h5>
13
13
  <hr/>
14
14
  <div class="p-3 mb-5 code highlight">
15
15
  <%= code_source %>
@@ -18,7 +18,7 @@
18
18
 
19
19
  <% unless prettified_output.nil? %>
20
20
  <div class="col border">
21
- <h5>Output</h5>
21
+ <h5 class="no_toc">Output</h5>
22
22
  <hr/>
23
23
  <div class="p-3 mb-5 code highlight">
24
24
  <%= prettified_output %>
@@ -28,9 +28,9 @@
28
28
 
29
29
  <div class="col border">
30
30
  <% if prettified_output.nil? %>
31
- <h5>Output</h5>
31
+ <h5 class="no_toc">Output</h5>
32
32
  <% else %>
33
- <h5>Rendered Output</h5>
33
+ <h5 class="no_toc">Rendered Output</h5>
34
34
  <% end %>
35
35
  <hr/>
36
36
  <div class="p-3 mb-5 border <%= render_raw? ? nil : 'code highlight' %>">
@@ -0,0 +1,25 @@
1
+ RSpec::Documentation.configure do |config|
2
+ # Force example tabs to have a consistent height to prevent content jumping.
3
+ # config.consistent_height = <%= RSpecDocumentation.configuration.consistent_height.inspect %>
4
+
5
+ # Set a maximum height for example tabs. Tabs will scroll if content exceeds this value.
6
+ # config.max_height = <%= RSpecDocumentation.configuration.max_height.inspect %>
7
+
8
+ # Enable or disable the table of contents for each page. This renders a list of all headings in
9
+ # the page, except the main heading.
10
+ # config.table_of_contents = <%= RSpecDocumentation.configuration.table_of_contents.inspect %>
11
+
12
+ # Enable or disable the index search above the navigation tree.
13
+ # config.index_search = <%= RSpecDocumentation.configuration.index_search.inspect %>
14
+
15
+ config.context do
16
+ # Define global context here, e.g. add some `let` blocks to make them available in every example.
17
+ #
18
+ # let(:foo) { 'bar' }
19
+ end
20
+ end
21
+
22
+ RSpec.configure do |config|
23
+ # Define RSpec configuration here.
24
+ # Note that your main `spec/spec_helper.rb` is not loaded unless you require it in this file.
25
+ end
@@ -5,7 +5,7 @@
5
5
  <ul class="nav nav-tabs" id="html-tabs-<%= element_id %>" role="tablist">
6
6
 
7
7
  <li class="nav-item" role="presentation">
8
- <button class="nav-link active"
8
+ <button class="no_toc nav-link active"
9
9
  id="code-source-<%= element_id %>-tab"
10
10
  data-bs-toggle="tab"
11
11
  data-bs-target="#code-source-<%= element_id %>"
@@ -17,7 +17,7 @@
17
17
 
18
18
  <% unless prettified_output.nil? %>
19
19
  <li class="nav-item" role="presentation">
20
- <button class="nav-link"
20
+ <button class="no_toc nav-link"
21
21
  id="html-source-<%= element_id %>-tab"
22
22
  data-bs-toggle="tab"
23
23
  data-bs-target="#html-source-<%= element_id %>"
@@ -29,7 +29,7 @@
29
29
  <% end %>
30
30
 
31
31
  <li class="nav-item" role="presentation">
32
- <button class="nav-link"
32
+ <button class="no_toc nav-link"
33
33
  id="rendered-<%= element_id %>-tab"
34
34
  data-bs-toggle="tab"
35
35
  data-bs-target="#rendered-<%= element_id %>"
@@ -40,7 +40,7 @@
40
40
  </li>
41
41
 
42
42
  <li class="nav-item bs-auto ms-auto mb-2">
43
- <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modal-<%= element_id %>-side-by-side">
43
+ <button type="button" class="no_toc btn btn-primary" data-bs-toggle="modal" data-bs-target="#modal-<%= element_id %>-side-by-side">
44
44
  View Side-by-side
45
45
  </button>
46
46
  </li>
@@ -6,12 +6,20 @@ Install _RSpec Documentation_:
6
6
  $ gem install rspec-documentation
7
7
  ```
8
8
 
9
+ Or add to your `Gemfile`:
10
+
11
+ ```ruby
12
+ gem 'rspec-documentation'
13
+ ```
14
+
9
15
  Initialize your project:
10
16
 
11
17
  ```console
12
18
  $ rspec-documentation
13
19
  ```
14
20
 
15
- A placeholder `000-Introduction.md` file with a basic example spec will be automatically generated.
21
+ A few placeholder files with a basic example spec will be automatically generated. See the [File System](file-system.html) section for full details on the directory layout.
16
22
 
17
23
  The documentation generator will provide you with a link to your interactive documentation bundle. Open it in your browser and then start adding specs to more _Markdown_ files. When you're ready, upload the static documentation bundle to your favourite _CDN_.
24
+
25
+ Whenever you add a `.md` file to your `rpsec-documentation/pages` directory, run `rspec-documentation` again to re-build your documentation bundle.
@@ -16,26 +16,11 @@ Running specs...
16
16
  Total build time: 0.63 seconds, examples executed in 0.0018 seconds.
17
17
  ```
18
18
 
19
- Documentation will only be generated if all tests pass. A summary of failures is provided if the suite does not run successfully:
20
-
21
- ```console
22
- $ rspec-documentation
23
-
24
- rspec-documentation/pages/030-Examples/010-Basic.md:23
25
-
26
- subject { 'my value' }
27
-
28
- it { is_expected.to eql 'not my value' }
19
+ ## Options
29
20
 
21
+ The following command-line options are supported:
30
22
 
31
- expected: "not my value"
32
- got: "my value"
33
-
34
- (compared using eql?)
35
-
36
- 6 examples, 1 failure.
37
-
38
- Failed examples:
39
-
40
- rspec-documentation/pages/030-Examples/010-Basic.md:23
41
- ```
23
+ |Option|Variant|Description|
24
+ |-|-|-|
25
+ |`--fail-fast`|`-F`|Abort the run after the first failure.|
26
+ |`--backtrace`|`-b`|Enable full backtrace.|
@@ -1,23 +1,23 @@
1
- ## Regular `it` blocks
1
+ # Regular `it` blocks
2
2
 
3
- ### Markdown
3
+ ## Markdown
4
4
 
5
5
  ````markdown
6
6
  ```rspec
7
- subject { 'my other value' }
7
+ subject(:value) { 'my other value' }
8
8
 
9
9
  it 'contains some expected text' do
10
- expect(subject).to eql 'other value'
10
+ expect(subjvalue).to eql 'other value'
11
11
  end
12
12
  ```
13
13
  ````
14
14
 
15
- ### Output
15
+ ## Output
16
16
 
17
17
  ```rspec
18
- subject { 'my other value' }
18
+ subject(:value) { 'my other value' }
19
19
 
20
20
  it 'contains some expected text' do
21
- expect(subject).to include 'other value'
21
+ expect(value).to include 'other value'
22
22
  end
23
23
  ```
@@ -1,4 +1,4 @@
1
- ## HTML
1
+ # HTML
2
2
 
3
3
  Setting the code block language to `rspec:html` indicates that the output should be treated as _HTML_ which adds a tab displaying auto-formatted _HTML_ and another tab showing the rendered output.
4
4
 
@@ -7,16 +7,16 @@ Setting the code block language to `rspec:html` indicates that the output should
7
7
  ````markdown
8
8
  ```rspec:html
9
9
  subject do
10
- <<~HTML
11
- <table class="table">
12
- <thead>
13
- <tr><th>Heading 1</th><th>Heading 2</th></tr>
14
- </thead>
15
- <tbody>
16
- <tr><td>Value 1</td><td>Value 2</td></tr>
17
- <tr><td>Value 3</td><td>Value 4</td></tr>
18
- </tbody>
19
- </table>
10
+ <<~HTML
11
+ <table class="table">
12
+ <thead>
13
+ <tr><th>Heading 1</th><th>Heading 2</th></tr>
14
+ </thead>
15
+ <tbody>
16
+ <tr><td>Value 1</td><td>Value 2</td></tr>
17
+ <tr><td>Value 3</td><td>Value 4</td></tr>
18
+ </tbody>
19
+ </table>
20
20
  HTML
21
21
  end
22
22
 
@@ -28,8 +28,8 @@ it { is_expected.to include 'Value 1' }
28
28
 
29
29
  ```rspec:html
30
30
  subject do
31
- <<~HTML
32
- <table class="table">
31
+ <<~HTML
32
+ <table class="table">
33
33
  <thead>
34
34
  <tr><th>Heading 1</th><th>Heading 2</th></tr>
35
35
  </thead>
@@ -37,7 +37,7 @@ subject do
37
37
  <tr><td>Value 1</td><td>Value 2</td></tr>
38
38
  <tr><td>Value 3</td><td>Value 4</td></tr>
39
39
  </tbody>
40
- </table>
40
+ </table>
41
41
  HTML
42
42
  end
43
43
 
@@ -24,9 +24,9 @@ it { is_expected.to include "\e[38;2;235;12;186mRGB PINK" }
24
24
  ```rspec:ansi
25
25
  subject do
26
26
  "\e[34mfoo\e[0m\e[0m \e[32mbar \e[36mfoo, bar, baz\e[0m\e[32m with " \
27
- "\e[36mqux\e[0m\e[32m and quux\e[0m\e[0m and corge with " \
28
- "\e[38;5;153mpale blue and " \
29
- "\e[38;2;235;12;186mRGB PINK\e[0m\e[0m"
27
+ "\e[36mqux\e[0m\e[32m and quux\e[0m\e[0m and corge with " \
28
+ "\e[38;5;153mpale blue and " \
29
+ "\e[38;2;235;12;186mRGB PINK\e[0m\e[0m"
30
30
  end
31
31
 
32
32
  it { is_expected.to include "\e[38;2;235;12;186mRGB PINK" }
@@ -6,7 +6,7 @@ If your code outputs _JSON_, use the ```` ```rspec:json ```` formatter to pretti
6
6
 
7
7
  ````markdown
8
8
  ```rspec:json
9
- subject do
9
+ subject(:json) do
10
10
  {
11
11
  'key' => 'value',
12
12
  'array' => [1, 2, 3],
@@ -16,7 +16,7 @@ subject do
16
16
  end
17
17
 
18
18
  it 'has expected key/value' do
19
- expect(JSON.parse(subject)).to include({ 'key' => 'value' })
19
+ expect(JSON.parse(json)).to include({ 'key' => 'value' })
20
20
  end
21
21
  ```
22
22
  ````
@@ -24,7 +24,7 @@ end
24
24
  ## Output
25
25
 
26
26
  ```rspec:json
27
- subject do
27
+ subject(:json) do
28
28
  {
29
29
  'key' => 'value',
30
30
  'array' => [1, 2, 3],
@@ -34,6 +34,6 @@ subject do
34
34
  end
35
35
 
36
36
  it 'has expected key/value' do
37
- expect(JSON.parse(subject)).to include({ 'key' => 'value' })
37
+ expect(JSON.parse(json)).to include({ 'key' => 'value' })
38
38
  end
39
39
  ```
@@ -6,7 +6,7 @@ If your code outputs _YAML_, use the ```` ```rspec:yaml ```` formatter to pretti
6
6
 
7
7
  ````markdown
8
8
  ```rspec:yaml
9
- subject do
9
+ subject(:yaml) do
10
10
  {
11
11
  'key' => 'value',
12
12
  'array' => [1, 2, 3],
@@ -16,7 +16,7 @@ subject do
16
16
  end
17
17
 
18
18
  it 'has expected key/value' do
19
- expect(YAML.safe_load(subject)).to include({ 'key' => 'value' })
19
+ expect(YAML.safe_load(yaml)).to include({ 'key' => 'value' })
20
20
  end
21
21
  ```
22
22
  ````
@@ -24,7 +24,7 @@ end
24
24
  ## Output
25
25
 
26
26
  ```rspec:yaml
27
- subject do
27
+ subject(:yaml) do
28
28
  {
29
29
  'key' => 'value',
30
30
  'array' => [1, 2, 3],
@@ -34,6 +34,6 @@ subject do
34
34
  end
35
35
 
36
36
  it 'has expected key/value' do
37
- expect(YAML.safe_load(subject)).to include({ 'key' => 'value' })
37
+ expect(YAML.safe_load(yaml)).to include({ 'key' => 'value' })
38
38
  end
39
39
  ```
@@ -6,10 +6,10 @@ If your code outputs _XML_, use the ```` ```rspec:xml ```` formatter to prettify
6
6
 
7
7
  ````markdown
8
8
  ```rspec:xml
9
- subject { '<?xml version="1.0" encoding="UTF-8"?><foo><bar>baz</bar></foo>' }
9
+ subject(:xml) { '<?xml version="1.0" encoding="UTF-8"?><foo><bar>baz</bar></foo>' }
10
10
 
11
11
  it 'has expected key/value' do
12
- expect(Nokogiri::XML.parse(subject).xpath('//foo/bar').text).to eql 'baz'
12
+ expect(Nokogiri::XML.parse(xml).xpath('//foo/bar').text).to eql 'baz'
13
13
  end
14
14
  ```
15
15
  ````
@@ -17,9 +17,9 @@ end
17
17
  ## Output
18
18
 
19
19
  ```rspec:xml
20
- subject { '<?xml version="1.0" encoding="UTF-8"?><foo><bar>baz</bar></foo>' }
20
+ subject(:xml) { '<?xml version="1.0" encoding="UTF-8"?><foo><bar>baz</bar></foo>' }
21
21
 
22
22
  it 'has expected key/value' do
23
- expect(Nokogiri::XML.parse(subject).xpath('//foo/bar').text).to eql 'baz'
23
+ expect(Nokogiri::XML.parse(xml).xpath('//foo/bar').text).to eql 'baz'
24
24
  end
25
25
  ```
@@ -0,0 +1,13 @@
1
+ # Index Search
2
+
3
+ The index above the navigation tree is enabled by default.
4
+
5
+ To disable the index search, set `config.index_search = false`:
6
+
7
+ ```ruby
8
+ # rspec-documentation/spec_helper.rb
9
+
10
+ RSpec::Documentation.configure do |config|
11
+ config.index_search = false
12
+ end
13
+ ```
@@ -0,0 +1,35 @@
1
+ # Table of Contents
2
+
3
+ A table of contents for each page is generated by default. The items in the table of contents are derived from the headers in each section (i.e. _Markdown_ elements defined with one or more `#` characters).
4
+
5
+ To disable the table of contents, set `config.table_of_contents` to `false`:
6
+
7
+ ```ruby
8
+ # spec/spec_helper.rb
9
+
10
+ RSpec::Documentation.configure do |config|
11
+ config.table_of_contents = false # Default: true
12
+ end
13
+ ```
14
+
15
+ ## Overriding for Specific Pages
16
+
17
+ If you want to disable the Table of Contents globally but enable for specific pages, add the following anywhere in your _Markdown_ document:
18
+
19
+ ```markdown
20
+ * TOC
21
+ {:toc}
22
+ ```
23
+
24
+ ## Omit a Specific Header from Table of Contents
25
+
26
+ To omit a specific header element from the Table of Contents, add `{:.no_toc}` underneath the header:
27
+
28
+ ```markdown
29
+ ## Header included in Table of Contents
30
+
31
+ ## Header not included in Table of Contents
32
+ {:.no_toc}
33
+ ```
34
+
35
+ See the [`kramdown` documentation](https://kramdown.gettalong.org/converter/html.html#toc) for more details. Aside from injecting _RSpec_ examples into the output, each _Markdown_ document is passed transparently to _kramdown_ for processing.
@@ -0,0 +1,36 @@
1
+ # RuboCop
2
+
3
+ An extension gem for [RuboCop](https://rubocop.org) is available. The extension allows _RuboCop_ to extract all examples from your documentation pages and identify any failures. With the extension enabled, a `rubocop` run will include all of the examples in your documentation seamlessly.
4
+
5
+ It is highly recommended to use the official [`rubocop-rspec`](https://github.com/rubocop/rubocop-rspec) extension in conjunction with _RSpec::Documentation_.
6
+
7
+ ## Installation
8
+
9
+ Add the following to your `Gemfile`:
10
+
11
+ ```ruby
12
+ gem 'rubocop-rspec-documentation', require: false
13
+ ```
14
+
15
+ ## Configuration
16
+
17
+ Add the following configuration to your `.rubocop.yml` to enable the extension:
18
+
19
+ ```yaml
20
+ # .rubocop.yml
21
+
22
+ require:
23
+ - rubocop-rspec-documentation
24
+ ```
25
+
26
+ _RuboCop_ will now look for files in `rspec-documentation/pages/**/*.md` and the provided extension will do the required parsing/extracting/offsetting, allowing _RuboCop_ to work as normal.
27
+
28
+ The following cops are disabled for your documentation examples as they cannot be sensibly addressed within each example:
29
+
30
+ * `Naming/FileName`
31
+ * `Gemspec/RequiredRubyVersion`
32
+ * `Style/FrozenStringLiteralComment`
33
+
34
+ ## Autocorrect
35
+
36
+ There is currently an issue using auto-correct with _RuboCop_, causing infinite loops with indentation corrections. Possibly a bug in _RuboCop's_ extension mechanism - avoid using auto-correct with your _Markdown_ files until this has been resolved.
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'devpack'
3
4
  require 'nokogiri'
4
5
 
5
6
  RSpec::Documentation.configure do |config|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-documentation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Farrell
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-11 00:00:00.000000000 Z
11
+ date: 2023-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: htmlbeautifier
@@ -177,9 +177,11 @@ files:
177
177
  - lib/templates/layout.css.erb
178
178
  - lib/templates/layout.html.erb
179
179
  - lib/templates/layout.js.erb
180
+ - lib/templates/link.svg.erb
180
181
  - lib/templates/modal_spec.html.erb
181
182
  - lib/templates/moon.svg.erb
182
183
  - lib/templates/script_tags.html.erb
184
+ - lib/templates/spec_helper.rb.erb
183
185
  - lib/templates/stylesheet_links.html.erb
184
186
  - lib/templates/sun.svg.erb
185
187
  - lib/templates/tabbed_spec.html.erb
@@ -229,12 +231,15 @@ files:
229
231
  - rspec-documentation/pages/040-Spec Helper.md
230
232
  - rspec-documentation/pages/050-Linking.md
231
233
  - rspec-documentation/pages/060-Configuration.md
232
- - rspec-documentation/pages/060-Configuration/010-Context.md
233
- - rspec-documentation/pages/060-Configuration/020-Build Paths.md
234
- - rspec-documentation/pages/060-Configuration/030-Attribution.md
235
- - rspec-documentation/pages/060-Configuration/040-Hooks.md
236
- - rspec-documentation/pages/060-Configuration/050-Consistent Height.md
234
+ - rspec-documentation/pages/060-Configuration/Attribution.md
235
+ - rspec-documentation/pages/060-Configuration/Build Paths.md
236
+ - rspec-documentation/pages/060-Configuration/Consistent Height.md
237
+ - rspec-documentation/pages/060-Configuration/Context.md
238
+ - rspec-documentation/pages/060-Configuration/Hooks.md
239
+ - rspec-documentation/pages/060-Configuration/Index Search.md
240
+ - rspec-documentation/pages/060-Configuration/Table of Contents.md
237
241
  - rspec-documentation/pages/070-Publishing.md
242
+ - rspec-documentation/pages/080-Rubocop.md
238
243
  - rspec-documentation/pages/500-License.md
239
244
  - rspec-documentation/spec_helper.rb
240
245
  - sig/rspec/documentation.rbs