rdoc 6.15.0 → 7.0.1

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +187 -0
  3. data/History.rdoc +1 -1
  4. data/LEGAL.rdoc +6 -0
  5. data/README.md +20 -3
  6. data/lib/rdoc/code_object/any_method.rb +15 -7
  7. data/lib/rdoc/code_object/class_module.rb +13 -0
  8. data/lib/rdoc/code_object/constant.rb +9 -0
  9. data/lib/rdoc/code_object/method_attr.rb +13 -1
  10. data/lib/rdoc/code_object/top_level.rb +31 -18
  11. data/lib/rdoc/comment.rb +190 -8
  12. data/lib/rdoc/generator/aliki.rb +183 -0
  13. data/lib/rdoc/generator/darkfish.rb +5 -1
  14. data/lib/rdoc/generator/template/aliki/_aside_toc.rhtml +8 -0
  15. data/lib/rdoc/generator/template/aliki/_footer.rhtml +23 -0
  16. data/lib/rdoc/generator/template/aliki/_head.rhtml +158 -0
  17. data/lib/rdoc/generator/template/aliki/_header.rhtml +56 -0
  18. data/lib/rdoc/generator/template/aliki/_icons.rhtml +208 -0
  19. data/lib/rdoc/generator/template/aliki/_sidebar_ancestors.rhtml +16 -0
  20. data/lib/rdoc/generator/template/aliki/_sidebar_classes.rhtml +15 -0
  21. data/lib/rdoc/generator/template/aliki/_sidebar_extends.rhtml +25 -0
  22. data/lib/rdoc/generator/template/aliki/_sidebar_includes.rhtml +25 -0
  23. data/lib/rdoc/generator/template/aliki/_sidebar_installed.rhtml +16 -0
  24. data/lib/rdoc/generator/template/aliki/_sidebar_methods.rhtml +41 -0
  25. data/lib/rdoc/generator/template/aliki/_sidebar_pages.rhtml +67 -0
  26. data/lib/rdoc/generator/template/aliki/_sidebar_search.rhtml +15 -0
  27. data/lib/rdoc/generator/template/aliki/_sidebar_sections.rhtml +21 -0
  28. data/lib/rdoc/generator/template/aliki/_sidebar_toggle.rhtml +3 -0
  29. data/lib/rdoc/generator/template/aliki/class.rhtml +218 -0
  30. data/lib/rdoc/generator/template/aliki/css/rdoc.css +1944 -0
  31. data/lib/rdoc/generator/template/aliki/index.rhtml +22 -0
  32. data/lib/rdoc/generator/template/aliki/js/aliki.js +498 -0
  33. data/lib/rdoc/generator/template/aliki/js/c_highlighter.js +299 -0
  34. data/lib/rdoc/generator/template/aliki/js/search_controller.js +120 -0
  35. data/lib/rdoc/generator/template/aliki/js/search_navigation.js +105 -0
  36. data/lib/rdoc/generator/template/aliki/js/search_ranker.js +239 -0
  37. data/lib/rdoc/generator/template/aliki/js/theme-toggle.js +112 -0
  38. data/lib/rdoc/generator/template/aliki/page.rhtml +18 -0
  39. data/lib/rdoc/generator/template/aliki/servlet_not_found.rhtml +14 -0
  40. data/lib/rdoc/generator/template/aliki/servlet_root.rhtml +65 -0
  41. data/lib/rdoc/generator/template/darkfish/_footer.rhtml +3 -3
  42. data/lib/rdoc/generator/template/darkfish/_head.rhtml +14 -19
  43. data/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +8 -8
  44. data/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +8 -8
  45. data/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +7 -6
  46. data/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml +6 -6
  47. data/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +19 -19
  48. data/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml +2 -2
  49. data/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml +1 -0
  50. data/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +3 -3
  51. data/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +14 -14
  52. data/lib/rdoc/generator/template/darkfish/class.rhtml +62 -62
  53. data/lib/rdoc/generator/template/darkfish/index.rhtml +4 -3
  54. data/lib/rdoc/generator/template/darkfish/page.rhtml +2 -1
  55. data/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml +2 -1
  56. data/lib/rdoc/generator/template/darkfish/servlet_root.rhtml +19 -19
  57. data/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +19 -17
  58. data/lib/rdoc/generator/template/json_index/js/searcher.js +43 -6
  59. data/lib/rdoc/generator.rb +1 -0
  60. data/lib/rdoc/markup/pre_process.rb +34 -10
  61. data/lib/rdoc/markup/to_ansi.rb +4 -0
  62. data/lib/rdoc/markup/to_bs.rb +4 -0
  63. data/lib/rdoc/markup/to_html.rb +6 -4
  64. data/lib/rdoc/markup/to_rdoc.rb +11 -3
  65. data/lib/rdoc/options.rb +21 -10
  66. data/lib/rdoc/parser/c.rb +15 -46
  67. data/lib/rdoc/parser/prism_ruby.rb +121 -113
  68. data/lib/rdoc/parser/ruby.rb +8 -8
  69. data/lib/rdoc/parser/ruby_tools.rb +5 -7
  70. data/lib/rdoc/parser/simple.rb +4 -21
  71. data/lib/rdoc/rdoc.rb +1 -0
  72. data/lib/rdoc/rubygems_hook.rb +3 -3
  73. data/lib/rdoc/text.rb +1 -1
  74. data/lib/rdoc/token_stream.rb +13 -1
  75. data/lib/rdoc/tom_doc.rb +1 -1
  76. data/lib/rdoc/version.rb +1 -1
  77. data/rdoc.gemspec +1 -1
  78. metadata +33 -5
  79. data/CONTRIBUTING.rdoc +0 -219
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 737b80cad7809fc0b20efe70270867bcc3a7f3ae7c5c0e1f818769b8ab40c7cc
4
- data.tar.gz: 6754787e054cab04658a068f8e3a2be8cacb1473991d91a330beb0118bf22930
3
+ metadata.gz: 4f5632459a5400e7f62d6f4875c8600a78649d0f3e2d79437eecbae45b0b5041
4
+ data.tar.gz: 8e81da45966c3ca65f53b0b43b38b933e532dc20d0788ae0b170bd8faf2edfe1
5
5
  SHA512:
6
- metadata.gz: fad664b000fbb058f96f2e7f032ba767b86213a21380cf584d30ff34710acc5c383bc5053b2a06e3e7190c9f4188d397ba7bc9be226d82231fd2bad76c046258
7
- data.tar.gz: 5afe676ff848a49515c6fba65fc5e8a4b765c5e52af6c0128caa36a7a1253a41fc3ac0b0ef2098f74fd69269e285c8d3ec67128cc631b60c97062c5c9fe7cbc0
6
+ metadata.gz: b0f95f6fdafee7c024137947be2297a5db3c9ee14cbf7b5c4d5bc26157dbe5adb58ba8f8877ea3b5bf951e3276fd9a45c85b6b169b1c76cbcfd7c61b9a7697cf
7
+ data.tar.gz: f010caf60fc595404dd240e23bdfeddcc5cd0a626725a608d1c5107adb63bb4cda834d6b89f1c27772003dbec4fcfc3202ebd4103b4e180262c99faa499be9fb
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,187 @@
1
+ # Contributing to RDoc
2
+
3
+ Thank you for your interest in contributing to RDoc! This document provides guidelines and instructions for contributing.
4
+
5
+ ## Reporting Bugs
6
+
7
+ If you think you found a bug, open an issue on the [issue tracker](https://github.com/ruby/rdoc/issues) on GitHub.
8
+
9
+ When reporting a bug:
10
+
11
+ - Include a sample file that illustrates the problem, or link to the repository/gem associated with the bug
12
+ - Include steps to reproduce the issue
13
+
14
+ ## Development Setup
15
+
16
+ RDoc uses Bundler for development. To get started:
17
+
18
+ ```bash
19
+ bundle install
20
+ bundle exec rake
21
+ ```
22
+
23
+ This will install dependencies and run the tests.
24
+
25
+ If you're working on CSS or templates, you'll also want Node dependencies for the CSS linter:
26
+
27
+ ```bash
28
+ npm install
29
+ ```
30
+
31
+ If tests don't pass on the first run, check the [GitHub Actions page](https://github.com/ruby/rdoc/actions) to see if there are any known failures.
32
+
33
+ **Note:** Generated parser files are committed to the repository. If you delete them (for example via `bundle exec rake clean`) or you change any `.ry`/`.kpeg` parser sources, run `bundle exec rake generate` before running tests.
34
+
35
+ ## Running Tests
36
+
37
+ ```bash
38
+ # Run all tests (default task)
39
+ bundle exec rake
40
+
41
+ # Run unit tests only (excludes RubyGems integration)
42
+ bundle exec rake normal_test
43
+
44
+ # Run RubyGems integration tests only
45
+ bundle exec rake rubygems_test
46
+
47
+ # Verify generated parser files are current (CI check)
48
+ bundle exec rake verify_generated
49
+ ```
50
+
51
+ - **Test Framework:** [`test-unit`](https://github.com/test-unit/test-unit)
52
+ - **Test Location:** `test/` directory
53
+ - **Test Helper:** `test/lib/helper.rb`
54
+
55
+ ## Linting
56
+
57
+ ### RuboCop (Ruby Code)
58
+
59
+ ```bash
60
+ # Check Ruby code style
61
+ bundle exec rubocop
62
+
63
+ # Auto-fix style issues
64
+ bundle exec rubocop -A
65
+ ```
66
+
67
+ ### Herb Linter (ERB/RHTML Templates)
68
+
69
+ ```bash
70
+ # Lint ERB template files
71
+ npx @herb-tools/linter "**/*.rhtml"
72
+
73
+ # Lint specific directory
74
+ npx @herb-tools/linter "lib/**/*.rhtml"
75
+ ```
76
+
77
+ **Template Location:** `lib/rdoc/generator/template/**/*.rhtml`
78
+
79
+ ### Stylelint (CSS Files)
80
+
81
+ ```bash
82
+ # Lint CSS files
83
+ npm run lint:css
84
+
85
+ # Auto-fix style issues
86
+ npm run lint:css -- --fix
87
+ ```
88
+
89
+ ## Parser Generation
90
+
91
+ RDoc uses generated parsers for Markdown and RD formats.
92
+
93
+ ```bash
94
+ # Generate all parser files from sources
95
+ bundle exec rake generate
96
+
97
+ # Remove generated parser files
98
+ bundle exec rake clean
99
+
100
+ # Verify generated files are in sync with sources (CI check)
101
+ bundle exec rake verify_generated
102
+ ```
103
+
104
+ **Source Files** (edit these):
105
+
106
+ - `lib/rdoc/rd/block_parser.ry` → generates `block_parser.rb` via racc
107
+ - `lib/rdoc/rd/inline_parser.ry` → generates `inline_parser.rb` via racc
108
+ - `lib/rdoc/markdown.kpeg` → generates `markdown.rb` via kpeg
109
+ - `lib/rdoc/markdown/literals.kpeg` → generates `literals.rb` via kpeg
110
+
111
+ **Important:**
112
+
113
+ - Generated parser files **should be committed** to the repository
114
+ - Do not edit generated `.rb` parser files directly
115
+ - After modifying `.ry` or `.kpeg` source files, run `bundle exec rake generate`
116
+ - CI runs `rake verify_generated` to ensure generated files are in sync with their sources
117
+
118
+ ## Documentation Generation
119
+
120
+ ```bash
121
+ # Generate documentation (creates _site directory)
122
+ bundle exec rake rdoc
123
+
124
+ # Force regenerate documentation
125
+ bundle exec rake rerdoc
126
+
127
+ # Show documentation coverage
128
+ bundle exec rake rdoc:coverage
129
+ bundle exec rake coverage
130
+ ```
131
+
132
+ - **Output Directory:** `_site/` (GitHub Pages compatible)
133
+ - **Configuration:** `.rdoc_options` and `.document`
134
+
135
+ ## Themes
136
+
137
+ RDoc ships with two HTML themes:
138
+
139
+ - **Aliki** (default) - Modern theme with improved styling and navigation
140
+ - **Darkfish** (deprecated) - Classic theme, will be removed in v8.0
141
+
142
+ New feature development should focus on the Aliki theme. Darkfish will continue to receive bug fixes but no new features.
143
+
144
+ Theme templates are located at `lib/rdoc/generator/template/<theme>/`.
145
+
146
+ ## Project Structure
147
+
148
+ ```
149
+ lib/rdoc/
150
+ ├── rdoc.rb # Main entry point (RDoc::RDoc class)
151
+ ├── version.rb # Version constant
152
+ ├── task.rb # Rake task integration
153
+ ├── parser/ # Source code parsers
154
+ │ ├── ruby.rb # Ruby code parser
155
+ │ ├── c.rb # C extension parser
156
+ │ ├── prism_ruby.rb # Prism-based Ruby parser
157
+ │ └── ...
158
+ ├── generator/ # Documentation generators
159
+ │ ├── aliki.rb # HTML generator (default theme)
160
+ │ ├── darkfish.rb # HTML generator (deprecated, will be removed in v8.0)
161
+ │ ├── markup.rb # Markup format generator
162
+ │ ├── ri.rb # RI command generator
163
+ │ └── template/ # ERB templates
164
+ │ ├── aliki/ # Aliki theme (default)
165
+ │ └── darkfish/ # Darkfish theme (deprecated)
166
+ ├── markup/ # Markup parsing and formatting
167
+ ├── code_object/ # AST objects for documented items
168
+ ├── markdown.kpeg # Parser source (edit this)
169
+ ├── markdown.rb # Generated parser (do not edit)
170
+ ├── markdown/ # Markdown parsing
171
+ │ ├── literals.kpeg # Parser source (edit this)
172
+ │ └── literals.rb # Generated parser (do not edit)
173
+ ├── rd/ # RD format parsing
174
+ │ ├── block_parser.ry # Parser source (edit this)
175
+ │ ├── block_parser.rb # Generated parser (do not edit)
176
+ │ ├── inline_parser.ry # Parser source (edit this)
177
+ │ └── inline_parser.rb # Generated parser (do not edit)
178
+ └── ri/ # RI (Ruby Info) tool
179
+
180
+ test/ # Test files
181
+ ├── lib/helper.rb # Test helpers
182
+ └── rdoc/ # Main test directory
183
+ ```
184
+
185
+ ## Code of Conduct
186
+
187
+ Please be respectful and constructive in all interactions. We're all here to make RDoc better!
data/History.rdoc CHANGED
@@ -163,7 +163,7 @@
163
163
  * Moved old DEVELOPERS file to CONTRIBUTING to match github conventions.
164
164
  * TomDoc output now has a "Returns" heading. Issue #234 by Brian Henderson
165
165
  * Metaprogrammed methods can now use the :args: directive in addition to the
166
- :call-seq: directive. Issue #236 by Mike Moore.
166
+ \:call-seq: directive. Issue #236 by Mike Moore.
167
167
  * Sections can be linked to using "@" like labels. If a section and a label
168
168
  have the same name the section will be preferred. Issue #233 by Brian
169
169
  Henderson.
data/LEGAL.rdoc CHANGED
@@ -4,6 +4,12 @@
4
4
 
5
5
  The files in this distribution are covered by the Ruby license (see LICENSE) except the features mentioned below:
6
6
 
7
+ Aliki::
8
+ Aliki was written by Stan Lo and is included under the MIT license.
9
+
10
+ * lib/rdoc/generator/aliki.rb
11
+ * lib/rdoc/generator/template/aliki/*
12
+
7
13
  Darkfish::
8
14
  Darkfish was written by Michael Granger and is included under the BSD 3-Clause
9
15
  license. Darkfish contains images from the Silk Icons set by Mark James.
data/README.md CHANGED
@@ -48,7 +48,7 @@ require 'rdoc/rdoc'
48
48
 
49
49
  options = RDoc::Options.new
50
50
  options.files = ['a.rb', 'b.rb']
51
- options.setup_generator 'darkfish'
51
+ options.setup_generator 'aliki'
52
52
  # see RDoc::Options
53
53
 
54
54
  rdoc = RDoc::RDoc.new
@@ -90,7 +90,24 @@ To determine how well your project is documented run `rdoc -C lib` to get a docu
90
90
 
91
91
  ## Theme Options
92
92
 
93
- There are a few community-maintained themes for RDoc:
93
+ RDoc ships with two built-in themes:
94
+
95
+ - **Aliki** (default) - A modern, clean theme with improved navigation and search
96
+ - **Darkfish** (deprecated) - The classic theme, will be removed in v8.0
97
+
98
+ To use the Darkfish theme instead of the default Aliki theme:
99
+
100
+ ```shell
101
+ rdoc --format darkfish
102
+ ```
103
+
104
+ Or in your `.rdoc_options` file:
105
+
106
+ ```yaml
107
+ generator_name: darkfish
108
+ ```
109
+
110
+ There are also a few community-maintained themes for RDoc:
94
111
 
95
112
  - [rorvswild-theme-rdoc](https://github.com/BaseSecrete/rorvswild-theme-rdoc)
96
113
  - [hanna](https://github.com/jeremyevans/hanna) (a fork maintained by [Jeremy Evans](https://github.com/jeremyevans))
@@ -99,7 +116,7 @@ Please follow the theme's README for usage instructions.
99
116
 
100
117
  ## Bugs
101
118
 
102
- See CONTRIBUTING.rdoc for information on filing a bug report. It's OK to file a bug report for anything you're having a problem with. If you can't figure out how to make RDoc produce the output you like that is probably a documentation bug.
119
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for information on filing a bug report. It's OK to file a bug report for anything you're having a problem with. If you can't figure out how to make RDoc produce the output you like that is probably a documentation bug.
103
120
 
104
121
  ## License
105
122
 
@@ -351,7 +351,6 @@ class RDoc::AnyMethod < RDoc::MethodAttr
351
351
  return call_seq unless is_alias_for || !aliases.empty?
352
352
 
353
353
  method_name = self.name
354
- method_name = method_name[0, 1] if method_name =~ /\A\[/
355
354
 
356
355
  entries = call_seq.split "\n"
357
356
 
@@ -360,15 +359,24 @@ class RDoc::AnyMethod < RDoc::MethodAttr
360
359
  ignore << is_alias_for.name
361
360
  ignore.concat is_alias_for.aliases.map(&:name)
362
361
  end
363
- ignore.map! { |n| n =~ /\A\[/ ? /\[.*\]/ : n}
362
+
364
363
  ignore.delete(method_name)
365
- ignore = Regexp.union(ignore)
364
+ ignore_bracket_methods, ignore_other_methods = ignore.partition {|i| i.start_with?('[') }
366
365
 
367
- matching = entries.reject do |entry|
368
- entry =~ /^\w*\.?#{ignore}[$\(\s]/ or
369
- entry =~ /\s#{ignore}\s/
366
+ if ignore_other_methods.any?
367
+ ignore_union = Regexp.union(ignore_other_methods)
368
+ entries.reject! do |entry|
369
+ /\A(?:\w*\.)?#{ignore_union}(?:[(\s]|\z)/.match?(entry) ||
370
+ /\s#{ignore_union}\s/.match?(entry)
371
+ end
372
+ end
373
+ if ignore_bracket_methods.any?
374
+ entries.reject! do |entry|
375
+ # Ignore `receiver[arg] -> return_type` `[](arg)` `[]`
376
+ /\A\w*\[.*?\](?:[(\s]|\z)/.match?(entry)
377
+ end
370
378
  end
371
379
 
372
- matching.empty? ? nil : matching.join("\n")
380
+ entries.empty? ? nil : entries.join("\n")
373
381
  end
374
382
  end
@@ -689,6 +689,9 @@ class RDoc::ClassModule < RDoc::Context
689
689
 
690
690
  ##
691
691
  # Search record used by RDoc::Generator::JsonIndex
692
+ #
693
+ # TODO: Remove this method after dropping the darkfish theme and JsonIndex generator.
694
+ # Use #search_snippet instead for getting documentation snippets.
692
695
 
693
696
  def search_record
694
697
  [
@@ -702,6 +705,16 @@ class RDoc::ClassModule < RDoc::Context
702
705
  ]
703
706
  end
704
707
 
708
+ ##
709
+ # Returns an HTML snippet of the first comment for search results.
710
+
711
+ def search_snippet
712
+ first_comment = @comment_location.first&.first
713
+ return '' unless first_comment && !first_comment.empty?
714
+
715
+ snippet(first_comment)
716
+ end
717
+
705
718
  ##
706
719
  # Sets the store for this class or module and its contained code objects.
707
720
 
@@ -154,6 +154,15 @@ class RDoc::Constant < RDoc::CodeObject
154
154
  "#{@parent.path}##{@name}"
155
155
  end
156
156
 
157
+ ##
158
+ # Returns an HTML snippet of the comment for search results.
159
+
160
+ def search_snippet
161
+ return '' if comment.empty?
162
+
163
+ snippet(comment)
164
+ end
165
+
157
166
  def pretty_print(q) # :nodoc:
158
167
  q.group 2, "[#{self.class.name} #{full_name}", "]" do
159
168
  unless comment.empty? then
@@ -375,6 +375,9 @@ class RDoc::MethodAttr < RDoc::CodeObject
375
375
  ##
376
376
  # Used by RDoc::Generator::JsonIndex to create a record for the search
377
377
  # engine.
378
+ #
379
+ # TODO: Remove this method after dropping the darkfish theme and JsonIndex generator.
380
+ # Use #search_snippet instead for getting documentation snippets.
378
381
 
379
382
  def search_record
380
383
  [
@@ -384,10 +387,19 @@ class RDoc::MethodAttr < RDoc::CodeObject
384
387
  @parent.full_name,
385
388
  path,
386
389
  params,
387
- snippet(@comment),
390
+ search_snippet,
388
391
  ]
389
392
  end
390
393
 
394
+ ##
395
+ # Returns an HTML snippet of the comment for search results.
396
+
397
+ def search_snippet
398
+ return '' if @comment.empty?
399
+
400
+ snippet(@comment)
401
+ end
402
+
391
403
  def to_s # :nodoc:
392
404
  if @is_alias_for
393
405
  "#{self.class.name}: #{full_name} -> #{is_alias_for}"
@@ -16,6 +16,16 @@ class RDoc::TopLevel < RDoc::Context
16
16
 
17
17
  attr_accessor :absolute_name
18
18
 
19
+ ##
20
+ # Base name of this file
21
+
22
+ attr_reader :base_name
23
+
24
+ ##
25
+ # Base name of this file without the extension
26
+
27
+ attr_reader :page_name
28
+
19
29
  ##
20
30
  # All the classes or modules that were declared in
21
31
  # this file. These are assigned to either +#classes_hash+
@@ -40,6 +50,14 @@ class RDoc::TopLevel < RDoc::Context
40
50
  @relative_name = relative_name
41
51
  @parser = nil
42
52
 
53
+ if relative_name
54
+ @base_name = File.basename(relative_name)
55
+ @page_name = @base_name.sub(/\.(rb|rdoc|txt|md)\z/i, '')
56
+ else
57
+ @base_name = nil
58
+ @page_name = nil
59
+ end
60
+
43
61
  @classes_or_modules = []
44
62
  end
45
63
 
@@ -105,13 +123,6 @@ class RDoc::TopLevel < RDoc::Context
105
123
  @classes_or_modules << mod
106
124
  end
107
125
 
108
- ##
109
- # Base name of this file
110
-
111
- def base_name
112
- File.basename @relative_name
113
- end
114
-
115
126
  alias name base_name
116
127
 
117
128
  ##
@@ -204,16 +215,6 @@ class RDoc::TopLevel < RDoc::Context
204
215
  end
205
216
  end
206
217
 
207
- ##
208
- # Base name of this file without the extension
209
-
210
- def page_name
211
- basename = File.basename @relative_name
212
- basename =~ /\.(rb|rdoc|txt|md)$/i
213
-
214
- $` || basename
215
- end
216
-
217
218
  ##
218
219
  # Path to this file for use with HTML generator output.
219
220
 
@@ -236,6 +237,9 @@ class RDoc::TopLevel < RDoc::Context
236
237
 
237
238
  ##
238
239
  # Search record used by RDoc::Generator::JsonIndex
240
+ #
241
+ # TODO: Remove this method after dropping the darkfish theme and JsonIndex generator.
242
+ # Use #search_snippet instead for getting documentation snippets.
239
243
 
240
244
  def search_record
241
245
  return unless @parser < RDoc::Parser::Text
@@ -247,10 +251,19 @@ class RDoc::TopLevel < RDoc::Context
247
251
  '',
248
252
  path,
249
253
  '',
250
- snippet(@comment),
254
+ search_snippet,
251
255
  ]
252
256
  end
253
257
 
258
+ ##
259
+ # Returns an HTML snippet of the comment for search results.
260
+
261
+ def search_snippet
262
+ return '' if @comment.empty?
263
+
264
+ snippet(@comment)
265
+ end
266
+
254
267
  ##
255
268
  # Is this TopLevel from a text file instead of a source code file?
256
269
 
data/lib/rdoc/comment.rb CHANGED
@@ -162,6 +162,12 @@ class RDoc::Comment
162
162
  self
163
163
  end
164
164
 
165
+ # Change normalized, when creating already normalized comment.
166
+
167
+ def normalized=(value)
168
+ @normalized = value
169
+ end
170
+
165
171
  ##
166
172
  # Was this text normalized?
167
173
 
@@ -223,14 +229,190 @@ class RDoc::Comment
223
229
  @format == 'tomdoc'
224
230
  end
225
231
 
226
- ##
227
- # Create a new parsed comment from a document
232
+ MULTILINE_DIRECTIVES = %w[call-seq].freeze # :nodoc:
228
233
 
229
- def self.from_document(document) # :nodoc:
230
- comment = RDoc::Comment.new('')
231
- comment.document = document
232
- comment.location = RDoc::TopLevel.new(document.file) if document.file
233
- comment
234
- end
234
+ # There are more, but already handled by RDoc::Parser::C
235
+ COLON_LESS_DIRECTIVES = %w[call-seq Document-method].freeze # :nodoc:
236
+
237
+ DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP = /\A(?<colon>\\?:|:?)(?<directive>[\w-]+):(?<param>.*)/
238
+
239
+ private_constant :MULTILINE_DIRECTIVES, :COLON_LESS_DIRECTIVES, :DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP
240
+
241
+ class << self
242
+
243
+ ##
244
+ # Create a new parsed comment from a document
235
245
 
246
+ def from_document(document) # :nodoc:
247
+ comment = RDoc::Comment.new('')
248
+ comment.document = document
249
+ comment.location = RDoc::TopLevel.new(document.file) if document.file
250
+ comment
251
+ end
252
+
253
+ # Parse comment, collect directives as an attribute and return [normalized_comment_text, directives_hash]
254
+ # This method expands include and removes everything not needed in the document text, such as
255
+ # private section, directive line, comment characters `# /* * */` and indent spaces.
256
+ #
257
+ # RDoc comment consists of include, directive, multiline directive, private section and comment text.
258
+ #
259
+ # Include
260
+ # # :include: filename
261
+ #
262
+ # Directive
263
+ # # :directive-without-value:
264
+ # # :directive-with-value: value
265
+ #
266
+ # Multiline directive (only :call-seq:)
267
+ # # :multiline-directive:
268
+ # # value1
269
+ # # value2
270
+ #
271
+ # Private section
272
+ # #--
273
+ # # private comment
274
+ # #++
275
+
276
+ def parse(text, filename, line_no, type, &include_callback)
277
+ case type
278
+ when :ruby
279
+ text = text.gsub(/^#+/, '') if text.start_with?('#')
280
+ private_start_regexp = /^-{2,}$/
281
+ private_end_regexp = /^\+{2}$/
282
+ indent_regexp = /^\s*/
283
+ when :c
284
+ private_start_regexp = /^(\s*\*)?-{2,}$/
285
+ private_end_regexp = /^(\s*\*)?\+{2}$/
286
+ indent_regexp = /^\s*(\/\*+|\*)?\s*/
287
+ text = text.gsub(/\s*\*+\/\s*\z/, '')
288
+ when :simple
289
+ # Unlike other types, this implementation only looks for two dashes at
290
+ # the beginning of the line. Three or more dashes are considered to be
291
+ # a rule and ignored.
292
+ private_start_regexp = /^-{2}$/
293
+ private_end_regexp = /^\+{2}$/
294
+ indent_regexp = /^\s*/
295
+ end
296
+
297
+ directives = {}
298
+ lines = text.split("\n")
299
+ in_private = false
300
+ comment_lines = []
301
+ until lines.empty?
302
+ line = lines.shift
303
+ read_lines = 1
304
+ if in_private
305
+ # If `++` appears in a private section that starts with `--`, private section ends.
306
+ in_private = false if line.match?(private_end_regexp)
307
+ line_no += read_lines
308
+ next
309
+ elsif line.match?(private_start_regexp)
310
+ # If `--` appears in a line, private section starts.
311
+ in_private = true
312
+ line_no += read_lines
313
+ next
314
+ end
315
+
316
+ prefix = line[indent_regexp]
317
+ prefix_indent = ' ' * prefix.size
318
+ line = line.byteslice(prefix.bytesize..)
319
+
320
+ if (directive_match = DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP.match(line))
321
+ colon = directive_match[:colon]
322
+ directive = directive_match[:directive]
323
+ raw_param = directive_match[:param]
324
+ param = raw_param.strip
325
+ else
326
+ colon = directive = raw_param = param = nil
327
+ end
328
+
329
+ if !directive
330
+ comment_lines << prefix_indent + line
331
+ elsif colon == '\\:'
332
+ # If directive is escaped, unescape it
333
+ comment_lines << prefix_indent + line.sub('\\:', ':')
334
+ elsif raw_param.start_with?(':') || (colon.empty? && !COLON_LESS_DIRECTIVES.include?(directive))
335
+ # Something like `:toto::` is not a directive
336
+ # Only few directives allows to start without a colon
337
+ comment_lines << prefix_indent + line
338
+ elsif directive == 'include'
339
+ filename_to_include = param
340
+ include_callback.call(filename_to_include, prefix_indent).lines.each { |l| comment_lines << l.chomp }
341
+ elsif MULTILINE_DIRECTIVES.include?(directive)
342
+ value_lines = take_multiline_directive_value_lines(directive, filename, line_no, lines, prefix_indent.size, indent_regexp, !param.empty?)
343
+ read_lines += value_lines.size
344
+ lines.shift(value_lines.size)
345
+ unless param.empty?
346
+ # Accept `:call-seq: first-line\n second-line` for now
347
+ value_lines.unshift(param)
348
+ end
349
+ value = value_lines.join("\n")
350
+ directives[directive] = [value.empty? ? nil : value, line_no]
351
+ else
352
+ directives[directive] = [param.empty? ? nil : param, line_no]
353
+ end
354
+ line_no += read_lines
355
+ end
356
+
357
+ normalized_comment = String.new(encoding: text.encoding) << normalize_comment_lines(comment_lines).join("\n")
358
+ [normalized_comment, directives]
359
+ end
360
+
361
+ # Remove preceding indent spaces and blank lines from the comment lines
362
+
363
+ private def normalize_comment_lines(lines)
364
+ blank_line_regexp = /\A\s*\z/
365
+ lines = lines.dup
366
+ lines.shift while lines.first&.match?(blank_line_regexp)
367
+ lines.pop while lines.last&.match?(blank_line_regexp)
368
+
369
+ min_spaces = lines.map do |l|
370
+ l.match(/\A *(?=\S)/)&.end(0)
371
+ end.compact.min
372
+ if min_spaces && min_spaces > 0
373
+ lines.map { |l| l[min_spaces..] || '' }
374
+ else
375
+ lines
376
+ end
377
+ end
378
+
379
+ # Take value lines of multiline directive
380
+
381
+ private def take_multiline_directive_value_lines(directive, filename, line_no, lines, base_indent_size, indent_regexp, has_param)
382
+ return [] if lines.empty?
383
+
384
+ first_indent_size = lines.first.match(indent_regexp).end(0)
385
+
386
+ # Blank line or unindented line is not part of multiline-directive value
387
+ return [] if first_indent_size <= base_indent_size
388
+
389
+ if has_param
390
+ # :multiline-directive: line1
391
+ # line2
392
+ # line3
393
+ #
394
+ value_lines = lines.take_while do |l|
395
+ l.rstrip.match(indent_regexp).end(0) > base_indent_size
396
+ end
397
+ min_indent = value_lines.map { |l| l.match(indent_regexp).end(0) }.min
398
+ value_lines.map { |l| l[min_indent..] }
399
+ else
400
+ # Take indented lines accepting blank lines between them
401
+ value_lines = lines.take_while do |l|
402
+ l = l.rstrip
403
+ indent = l[indent_regexp]
404
+ if indent == l || indent.size >= first_indent_size
405
+ true
406
+ end
407
+ end
408
+ value_lines.map! { |l| (l[first_indent_size..] || '').chomp }
409
+
410
+ if value_lines.size != lines.size && !value_lines.last.empty?
411
+ warn "#{filename}:#{line_no} Multiline directive :#{directive}: should end with a blank line."
412
+ end
413
+ value_lines.pop while value_lines.last&.empty?
414
+ value_lines
415
+ end
416
+ end
417
+ end
236
418
  end