rspec-documentation 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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