rdoc 8.0.0 → 8.1.0

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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +1 -3
  3. data/RI.md +75 -75
  4. data/exe/rdoc +2 -2
  5. data/lib/rdoc/code_object/alias.rb +71 -69
  6. data/lib/rdoc/code_object/any_method.rb +305 -303
  7. data/lib/rdoc/code_object/attr.rb +150 -148
  8. data/lib/rdoc/code_object/class_module.rb +798 -792
  9. data/lib/rdoc/code_object/constant.rb +175 -173
  10. data/lib/rdoc/code_object/context/section.rb +142 -138
  11. data/lib/rdoc/code_object/context.rb +926 -958
  12. data/lib/rdoc/code_object/extend.rb +7 -5
  13. data/lib/rdoc/code_object/include.rb +7 -5
  14. data/lib/rdoc/code_object/method_attr.rb +326 -319
  15. data/lib/rdoc/code_object/mixin.rb +97 -95
  16. data/lib/rdoc/code_object/normal_class.rb +77 -78
  17. data/lib/rdoc/code_object/normal_module.rb +61 -59
  18. data/lib/rdoc/code_object/require.rb +23 -39
  19. data/lib/rdoc/code_object/single_class.rb +21 -19
  20. data/lib/rdoc/code_object/top_level.rb +212 -219
  21. data/lib/rdoc/code_object.rb +305 -303
  22. data/lib/rdoc/comment.rb +275 -273
  23. data/lib/rdoc/cross_reference.rb +192 -190
  24. data/lib/rdoc/encoding.rb +105 -103
  25. data/lib/rdoc/erb_partial.rb +13 -11
  26. data/lib/rdoc/erbio.rb +29 -27
  27. data/lib/rdoc/generator/aliki.rb +161 -153
  28. data/lib/rdoc/generator/darkfish.rb +645 -635
  29. data/lib/rdoc/generator/json_index.rb +233 -229
  30. data/lib/rdoc/generator/markup.rb +164 -146
  31. data/lib/rdoc/generator/pot/message_extractor.rb +57 -51
  32. data/lib/rdoc/generator/pot/po.rb +52 -51
  33. data/lib/rdoc/generator/pot/po_entry.rb +138 -132
  34. data/lib/rdoc/generator/pot.rb +85 -81
  35. data/lib/rdoc/generator/ri.rb +23 -19
  36. data/lib/rdoc/generator/template/aliki/DESIGN.md +6 -4
  37. data/lib/rdoc/generator/template/aliki/_footer.rhtml +1 -1
  38. data/lib/rdoc/generator/template/aliki/_head.rhtml +10 -10
  39. data/lib/rdoc/generator/template/aliki/_header.rhtml +29 -44
  40. data/lib/rdoc/generator/template/aliki/_sidebar_search.rhtml +4 -4
  41. data/lib/rdoc/generator/template/aliki/css/rdoc.css +207 -178
  42. data/lib/rdoc/generator/template/aliki/js/aliki.js +60 -84
  43. data/lib/rdoc/generator/template/darkfish/_footer.rhtml +1 -1
  44. data/lib/rdoc/generator.rb +48 -46
  45. data/lib/rdoc/i18n/locale.rb +99 -95
  46. data/lib/rdoc/i18n/text.rb +109 -105
  47. data/lib/rdoc/i18n.rb +7 -5
  48. data/lib/rdoc/markdown/byte_runtime.rb +80 -0
  49. data/lib/rdoc/markdown.kpeg +15 -11
  50. data/lib/rdoc/markdown.rb +40 -47
  51. data/lib/rdoc/markup/block_quote.rb +12 -8
  52. data/lib/rdoc/markup/document.rb +127 -123
  53. data/lib/rdoc/markup/formatter.rb +219 -215
  54. data/lib/rdoc/markup/include.rb +33 -29
  55. data/lib/rdoc/markup/indented_paragraph.rb +37 -33
  56. data/lib/rdoc/markup/inline_parser.rb +281 -277
  57. data/lib/rdoc/markup/list.rb +80 -88
  58. data/lib/rdoc/markup/list_item.rb +73 -85
  59. data/lib/rdoc/markup/paragraph.rb +23 -19
  60. data/lib/rdoc/markup/parser.rb +501 -497
  61. data/lib/rdoc/markup/pre_process.rb +283 -279
  62. data/lib/rdoc/markup/raw.rb +2 -2
  63. data/lib/rdoc/markup/rule.rb +16 -12
  64. data/lib/rdoc/markup/to_ansi.rb +143 -139
  65. data/lib/rdoc/markup/to_bs.rb +72 -68
  66. data/lib/rdoc/markup/to_html.rb +594 -565
  67. data/lib/rdoc/markup/to_html_crossref.rb +234 -230
  68. data/lib/rdoc/markup/to_html_snippet.rb +232 -227
  69. data/lib/rdoc/markup/to_joined_paragraph.rb +36 -32
  70. data/lib/rdoc/markup/to_label.rb +63 -59
  71. data/lib/rdoc/markup/to_markdown.rb +212 -208
  72. data/lib/rdoc/markup/to_rdoc.rb +336 -332
  73. data/lib/rdoc/markup/to_table_of_contents.rb +66 -62
  74. data/lib/rdoc/markup/to_test.rb +60 -56
  75. data/lib/rdoc/markup/to_tt_only.rb +84 -80
  76. data/lib/rdoc/markup/verbatim.rb +62 -58
  77. data/lib/rdoc/markup.rb +198 -196
  78. data/lib/rdoc/options.rb +1063 -1061
  79. data/lib/rdoc/parser/c.rb +1039 -1037
  80. data/lib/rdoc/parser/changelog.rb +319 -315
  81. data/lib/rdoc/parser/markdown.rb +17 -13
  82. data/lib/rdoc/parser/rbs.rb +239 -235
  83. data/lib/rdoc/parser/rd.rb +17 -13
  84. data/lib/rdoc/parser/ruby.rb +1245 -1124
  85. data/lib/rdoc/parser/ruby_colorizer.rb +263 -213
  86. data/lib/rdoc/parser/simple.rb +31 -27
  87. data/lib/rdoc/parser/text.rb +12 -8
  88. data/lib/rdoc/parser.rb +228 -220
  89. data/lib/rdoc/rbs_helper.rb +1 -1
  90. data/lib/rdoc/rd/inline.rb +57 -53
  91. data/lib/rdoc/rd.rb +90 -88
  92. data/lib/rdoc/rdoc.rb +500 -491
  93. data/lib/rdoc/ri/driver.rb +1140 -1135
  94. data/lib/rdoc/ri/formatter.rb +7 -3
  95. data/lib/rdoc/ri/paths.rb +140 -136
  96. data/lib/rdoc/ri/servlet.rb +354 -350
  97. data/lib/rdoc/ri/store.rb +4 -2
  98. data/lib/rdoc/ri/task.rb +55 -51
  99. data/lib/rdoc/ri.rb +14 -12
  100. data/lib/rdoc/rubygems_hook.rb +183 -181
  101. data/lib/rdoc/server.rb +349 -347
  102. data/lib/rdoc/stats/normal.rb +46 -42
  103. data/lib/rdoc/stats/quiet.rb +39 -35
  104. data/lib/rdoc/stats/verbose.rb +35 -31
  105. data/lib/rdoc/stats.rb +365 -363
  106. data/lib/rdoc/store.rb +888 -902
  107. data/lib/rdoc/task.rb +260 -256
  108. data/lib/rdoc/text.rb +135 -133
  109. data/lib/rdoc/token_stream.rb +101 -93
  110. data/lib/rdoc/tom_doc.rb +203 -201
  111. data/lib/rdoc/version.rb +1 -1
  112. metadata +4 -5
  113. data/lib/rdoc/markdown/literals.kpeg +0 -21
  114. data/lib/rdoc/markdown/literals.rb +0 -454
data/lib/rdoc/comment.rb CHANGED
@@ -1,352 +1,354 @@
1
1
  # frozen_string_literal: true
2
- ##
3
- # A comment holds the text comment for a RDoc::CodeObject and provides a
4
- # unified way of cleaning it up and parsing it into an RDoc::Markup::Document.
5
- #
6
- # Each comment may have a different markup format set by #format=. By default
7
- # 'rdoc' is used. The :markup: directive tells RDoc which format to use.
8
- #
9
- # See {RDoc Markup Reference}[rdoc-ref:doc/markup_reference/rdoc.rdoc@Directive+for+Specifying+RDoc+Source+Format].
2
+ module RDoc
3
+ ##
4
+ # A comment holds the text comment for a RDoc::CodeObject and provides a
5
+ # unified way of cleaning it up and parsing it into an RDoc::Markup::Document.
6
+ #
7
+ # Each comment may have a different markup format set by #format=. By default
8
+ # 'rdoc' is used. The :markup: directive tells RDoc which format to use.
9
+ #
10
+ # See {RDoc Markup Reference}[rdoc-ref:doc/markup_reference/rdoc.rdoc@Directive+for+Specifying+RDoc+Source+Format].
10
11
 
11
12
 
12
- class RDoc::Comment
13
+ class Comment
13
14
 
14
- include RDoc::Text
15
+ include Text
15
16
 
16
- ##
17
- # The format of this comment. Defaults to RDoc::Markup
17
+ ##
18
+ # The format of this comment. Defaults to RDoc::Markup
18
19
 
19
- attr_reader :format
20
+ attr_reader :format
20
21
 
21
- ##
22
- # The RDoc::TopLevel this comment was found in
22
+ ##
23
+ # The RDoc::TopLevel this comment was found in
23
24
 
24
- attr_accessor :location
25
+ attr_accessor :location
25
26
 
26
- ##
27
- # Line where this Comment was written
27
+ ##
28
+ # Line where this Comment was written
28
29
 
29
- attr_accessor :line
30
+ attr_accessor :line
30
31
 
31
- ##
32
- # For duck-typing when merging classes at load time
32
+ ##
33
+ # For duck-typing when merging classes at load time
33
34
 
34
- alias file location # :nodoc:
35
+ alias file location # :nodoc:
35
36
 
36
- ##
37
- # The text for this comment
37
+ ##
38
+ # The text for this comment
38
39
 
39
- attr_reader :text
40
+ attr_reader :text
40
41
 
41
- ##
42
- # Alias for text
42
+ ##
43
+ # Alias for text
43
44
 
44
- alias to_s text
45
+ alias to_s text
45
46
 
46
- ##
47
- # Overrides the content returned by #parse. Use when there is no #text
48
- # source for this comment
47
+ ##
48
+ # Overrides the content returned by #parse. Use when there is no #text
49
+ # source for this comment
49
50
 
50
- attr_writer :document
51
+ attr_writer :document
51
52
 
52
- ##
53
- # Creates a new comment with +text+ that is found in the RDoc::TopLevel
54
- # +location+.
55
-
56
- def initialize(text = nil, location = nil, language = nil)
57
- @location = location
58
- @text = text.nil? ? nil : text.dup
59
- @language = language
53
+ ##
54
+ # Creates a new comment with +text+ that is found in the RDoc::TopLevel
55
+ # +location+.
60
56
 
61
- @document = nil
62
- @format = 'rdoc'
63
- @normalized = false
64
- end
57
+ def initialize(text = nil, location = nil, language = nil)
58
+ @location = location
59
+ @text = text.nil? ? nil : text.dup
60
+ @language = language
65
61
 
66
- ##
67
- #--
68
- # TODO deep copy @document
62
+ @document = nil
63
+ @format = 'rdoc'
64
+ @normalized = false
65
+ end
69
66
 
70
- def initialize_copy(copy) # :nodoc:
71
- @text = copy.text.dup
72
- end
67
+ ##
68
+ #--
69
+ # TODO deep copy @document
73
70
 
74
- def ==(other) # :nodoc:
75
- self.class === other and
76
- other.text == @text and other.location == @location
77
- end
71
+ def initialize_copy(copy) # :nodoc:
72
+ @text = copy.text.dup
73
+ end
78
74
 
79
- ##
80
- # A comment is empty if its text String is empty.
75
+ def ==(other) # :nodoc:
76
+ self.class === other and
77
+ other.text == @text and other.location == @location
78
+ end
81
79
 
82
- def empty?
83
- @text.empty? && (@document.nil? || @document.empty?)
84
- end
80
+ ##
81
+ # A comment is empty if its text String is empty.
85
82
 
86
- ##
87
- # HACK dubious
83
+ def empty?
84
+ @text.empty? && (@document.nil? || @document.empty?)
85
+ end
88
86
 
89
- def encode!(encoding)
90
- @text = String.new @text, encoding: encoding
91
- self
92
- end
87
+ ##
88
+ # HACK dubious
93
89
 
94
- ##
95
- # Sets the format of this comment and resets any parsed document
90
+ def encode!(encoding)
91
+ @text = String.new @text, encoding: encoding
92
+ self
93
+ end
96
94
 
97
- def format=(format)
98
- @format = format
99
- @document = nil
100
- end
95
+ ##
96
+ # Sets the format of this comment and resets any parsed document
101
97
 
102
- def inspect # :nodoc:
103
- location = @location ? @location.relative_name : '(unknown)'
98
+ def format=(format)
99
+ @format = format
100
+ @document = nil
101
+ end
104
102
 
105
- "#<%s:%x %s %p>" % [self.class, object_id, location, @text]
106
- end
103
+ def inspect # :nodoc:
104
+ location = @location ? @location.relative_name : '(unknown)'
107
105
 
108
- ##
109
- # Normalizes the text. See RDoc::Text#normalize_comment for details
106
+ "#<%s:%x %s %p>" % [self.class, object_id, location, @text]
107
+ end
110
108
 
111
- def normalize
112
- return self unless @text
113
- return self if @normalized # TODO eliminate duplicate normalization
109
+ ##
110
+ # Normalizes the text. See RDoc::Text#normalize_comment for details
114
111
 
115
- @text = normalize_comment @text
112
+ def normalize
113
+ return self unless @text
114
+ return self if @normalized # TODO eliminate duplicate normalization
116
115
 
117
- @normalized = true
116
+ @text = normalize_comment @text
118
117
 
119
- self
120
- end
118
+ @normalized = true
121
119
 
122
- # Change normalized, when creating already normalized comment.
120
+ self
121
+ end
123
122
 
124
- def normalized=(value)
125
- @normalized = value
126
- end
123
+ # Change normalized, when creating already normalized comment.
127
124
 
128
- ##
129
- # Was this text normalized?
125
+ def normalized=(value)
126
+ @normalized = value
127
+ end
130
128
 
131
- def normalized? # :nodoc:
132
- @normalized
133
- end
129
+ ##
130
+ # Was this text normalized?
134
131
 
135
- ##
136
- # Parses the comment into an RDoc::Markup::Document. The parsed document is
137
- # cached until the text is changed.
132
+ def normalized? # :nodoc:
133
+ @normalized
134
+ end
138
135
 
139
- def parse
140
- return @document if @document
136
+ ##
137
+ # Parses the comment into an RDoc::Markup::Document. The parsed document is
138
+ # cached until the text is changed.
141
139
 
142
- @document = super @text, @format
143
- @document.file = @location
144
- @document
145
- end
140
+ def parse
141
+ return @document if @document
146
142
 
147
- ##
148
- # Replaces this comment's text with +text+ and resets the parsed document.
149
- #
150
- # An error is raised if the comment contains a document but no text.
143
+ @document = super @text, @format
144
+ @document.file = @location
145
+ @document
146
+ end
151
147
 
152
- def text=(text)
153
- raise RDoc::Error, 'replacing document-only comment is not allowed' if
154
- @text.nil? and @document
148
+ ##
149
+ # Replaces this comment's text with +text+ and resets the parsed document.
150
+ #
151
+ # An error is raised if the comment contains a document but no text.
155
152
 
156
- @document = nil
157
- @text = text.nil? ? nil : text.dup
158
- end
153
+ def text=(text)
154
+ raise Error, 'replacing document-only comment is not allowed' if
155
+ @text.nil? and @document
159
156
 
160
- ##
161
- # Returns true if this comment is in TomDoc format.
157
+ @document = nil
158
+ @text = text.nil? ? nil : text.dup
159
+ end
162
160
 
163
- def tomdoc?
164
- @format == 'tomdoc'
165
- end
161
+ ##
162
+ # Returns true if this comment is in TomDoc format.
166
163
 
167
- MULTILINE_DIRECTIVES = %w[call-seq].freeze # :nodoc:
164
+ def tomdoc?
165
+ @format == 'tomdoc'
166
+ end
168
167
 
169
- # There are more, but already handled by RDoc::Parser::C
170
- COLON_LESS_DIRECTIVES = %w[call-seq Document-method].freeze # :nodoc:
168
+ MULTILINE_DIRECTIVES = %w[call-seq].freeze # :nodoc:
171
169
 
172
- DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP = /\A(?<colon>\\?:|:?)(?<directive>[\w-]+):(?<param>.*)/
170
+ # There are more, but already handled by RDoc::Parser::C
171
+ COLON_LESS_DIRECTIVES = %w[call-seq Document-method].freeze # :nodoc:
173
172
 
174
- private_constant :MULTILINE_DIRECTIVES, :COLON_LESS_DIRECTIVES, :DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP
173
+ DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP = /\A(?<colon>\\?:|:?)(?<directive>[\w-]+):(?<param>.*)/
175
174
 
176
- class << self
175
+ private_constant :MULTILINE_DIRECTIVES, :COLON_LESS_DIRECTIVES, :DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP
177
176
 
178
- ##
179
- # Create a new parsed comment from a document
177
+ class << self
180
178
 
181
- def from_document(document) # :nodoc:
182
- comment = RDoc::Comment.new('')
183
- comment.document = document
184
- comment.location = RDoc::TopLevel.new(document.file) if document.file
185
- comment
186
- end
179
+ ##
180
+ # Create a new parsed comment from a document
187
181
 
188
- # Parse comment, collect directives as an attribute and return [normalized_comment_text, directives_hash]
189
- # This method expands include and removes everything not needed in the document text, such as
190
- # private section, directive line, comment characters `# /* * */` and indent spaces.
191
- #
192
- # RDoc comment consists of include, directive, multiline directive, private section and comment text.
193
- #
194
- # Include
195
- # # :include: filename
196
- #
197
- # Directive
198
- # # :directive-without-value:
199
- # # :directive-with-value: value
200
- #
201
- # Multiline directive (only :call-seq:)
202
- # # :multiline-directive:
203
- # # value1
204
- # # value2
205
- #
206
- # Private section
207
- # #--
208
- # # private comment
209
- # #++
210
-
211
- def parse(text, filename, line_no, type, &include_callback)
212
- case type
213
- when :ruby
214
- text = text.gsub(/^#+/, '') if text.start_with?('#')
215
- private_start_regexp = /^-{2,}$/
216
- private_end_regexp = /^\+{2}$/
217
- indent_regexp = /^\s*/
218
- when :c
219
- private_start_regexp = /^(\s*\*)?-{2,}$/
220
- private_end_regexp = /^(\s*\*)?\+{2}$/
221
- indent_regexp = /^\s*(\/\*+|\*)?\s*/
222
- text = text.gsub(/\s*\*+\/\s*\z/, '')
223
- when :simple
224
- # Unlike other types, this implementation only looks for two dashes at
225
- # the beginning of the line. Three or more dashes are considered to be
226
- # a rule and ignored.
227
- private_start_regexp = /^-{2}$/
228
- private_end_regexp = /^\+{2}$/
229
- indent_regexp = /^\s*/
182
+ def from_document(document) # :nodoc:
183
+ comment = Comment.new('')
184
+ comment.document = document
185
+ comment.location = TopLevel.new(document.file) if document.file
186
+ comment
230
187
  end
231
188
 
232
- directives = {}
233
- lines = text.split("\n")
234
- in_private = false
235
- comment_lines = []
236
- until lines.empty?
237
- line = lines.shift
238
- read_lines = 1
239
- if in_private
240
- # If `++` appears in a private section that starts with `--`, private section ends.
241
- in_private = false if line.match?(private_end_regexp)
242
- line_no += read_lines
243
- next
244
- elsif line.match?(private_start_regexp)
245
- # If `--` appears in a line, private section starts.
246
- in_private = true
247
- line_no += read_lines
248
- next
189
+ # Parse comment, collect directives as an attribute and return [normalized_comment_text, directives_hash]
190
+ # This method expands include and removes everything not needed in the document text, such as
191
+ # private section, directive line, comment characters `# /* * */` and indent spaces.
192
+ #
193
+ # RDoc comment consists of include, directive, multiline directive, private section and comment text.
194
+ #
195
+ # Include
196
+ # # :include: filename
197
+ #
198
+ # Directive
199
+ # # :directive-without-value:
200
+ # # :directive-with-value: value
201
+ #
202
+ # Multiline directive (only :call-seq:)
203
+ # # :multiline-directive:
204
+ # # value1
205
+ # # value2
206
+ #
207
+ # Private section
208
+ # #--
209
+ # # private comment
210
+ # #++
211
+
212
+ def parse(text, filename, line_no, type, &include_callback)
213
+ case type
214
+ when :ruby
215
+ text = text.gsub(/^#+/, '') if text.start_with?('#')
216
+ private_start_regexp = /^-{2,}$/
217
+ private_end_regexp = /^\+{2}$/
218
+ indent_regexp = /^\s*/
219
+ when :c
220
+ private_start_regexp = /^(\s*\*)?-{2,}$/
221
+ private_end_regexp = /^(\s*\*)?\+{2}$/
222
+ indent_regexp = /^\s*(\/\*+|\*)?\s*/
223
+ text = text.gsub(/\s*\*+\/\s*\z/, '')
224
+ when :simple
225
+ # Unlike other types, this implementation only looks for two dashes at
226
+ # the beginning of the line. Three or more dashes are considered to be
227
+ # a rule and ignored.
228
+ private_start_regexp = /^-{2}$/
229
+ private_end_regexp = /^\+{2}$/
230
+ indent_regexp = /^\s*/
249
231
  end
250
232
 
251
- prefix = line[indent_regexp]
252
- prefix_indent = ' ' * prefix.size
253
- line = line.byteslice(prefix.bytesize..)
233
+ directives = {}
234
+ lines = text.split("\n")
235
+ in_private = false
236
+ comment_lines = []
237
+ until lines.empty?
238
+ line = lines.shift
239
+ read_lines = 1
240
+ if in_private
241
+ # If `++` appears in a private section that starts with `--`, private section ends.
242
+ in_private = false if line.match?(private_end_regexp)
243
+ line_no += read_lines
244
+ next
245
+ elsif line.match?(private_start_regexp)
246
+ # If `--` appears in a line, private section starts.
247
+ in_private = true
248
+ line_no += read_lines
249
+ next
250
+ end
254
251
 
255
- if (directive_match = DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP.match(line))
256
- colon = directive_match[:colon]
257
- directive = directive_match[:directive]
258
- raw_param = directive_match[:param]
259
- param = raw_param.strip
260
- else
261
- colon = directive = raw_param = param = nil
262
- end
252
+ prefix = line[indent_regexp]
253
+ prefix_indent = ' ' * prefix.size
254
+ line = line.byteslice(prefix.bytesize..)
255
+
256
+ if (directive_match = DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP.match(line))
257
+ colon = directive_match[:colon]
258
+ directive = directive_match[:directive]
259
+ raw_param = directive_match[:param]
260
+ param = raw_param.strip
261
+ else
262
+ colon = directive = raw_param = param = nil
263
+ end
263
264
 
264
- if !directive
265
- comment_lines << prefix_indent + line
266
- elsif colon == '\\:'
267
- # If directive is escaped, unescape it
268
- comment_lines << prefix_indent + line.sub('\\:', ':')
269
- elsif raw_param.start_with?(':') || (colon.empty? && !COLON_LESS_DIRECTIVES.include?(directive))
270
- # Something like `:toto::` is not a directive
271
- # Only few directives allows to start without a colon
272
- comment_lines << prefix_indent + line
273
- elsif directive == 'include'
274
- filename_to_include = param
275
- include_callback.call(filename_to_include, prefix_indent).lines.each { |l| comment_lines << l.chomp }
276
- elsif MULTILINE_DIRECTIVES.include?(directive)
277
- value_lines = take_multiline_directive_value_lines(directive, filename, line_no, lines, prefix_indent.size, indent_regexp, !param.empty?)
278
- read_lines += value_lines.size
279
- lines.shift(value_lines.size)
280
- unless param.empty?
281
- # Accept `:call-seq: first-line\n second-line` for now
282
- value_lines.unshift(param)
265
+ if !directive
266
+ comment_lines << prefix_indent + line
267
+ elsif colon == '\\:'
268
+ # If directive is escaped, unescape it
269
+ comment_lines << prefix_indent + line.sub('\\:', ':')
270
+ elsif raw_param.start_with?(':') || (colon.empty? && !COLON_LESS_DIRECTIVES.include?(directive))
271
+ # Something like `:toto::` is not a directive
272
+ # Only few directives allows to start without a colon
273
+ comment_lines << prefix_indent + line
274
+ elsif directive == 'include'
275
+ filename_to_include = param
276
+ include_callback.call(filename_to_include, prefix_indent).lines.each { |l| comment_lines << l.chomp }
277
+ elsif MULTILINE_DIRECTIVES.include?(directive)
278
+ value_lines = take_multiline_directive_value_lines(directive, filename, line_no, lines, prefix_indent.size, indent_regexp, !param.empty?)
279
+ read_lines += value_lines.size
280
+ lines.shift(value_lines.size)
281
+ unless param.empty?
282
+ # Accept `:call-seq: first-line\n second-line` for now
283
+ value_lines.unshift(param)
284
+ end
285
+ value = value_lines.join("\n")
286
+ directives[directive] = [value.empty? ? nil : value, line_no]
287
+ else
288
+ directives[directive] = [param.empty? ? nil : param, line_no]
283
289
  end
284
- value = value_lines.join("\n")
285
- directives[directive] = [value.empty? ? nil : value, line_no]
286
- else
287
- directives[directive] = [param.empty? ? nil : param, line_no]
290
+ line_no += read_lines
288
291
  end
289
- line_no += read_lines
292
+
293
+ normalized_comment = String.new(encoding: text.encoding) << normalize_comment_lines(comment_lines).join("\n")
294
+ [normalized_comment, directives]
290
295
  end
291
296
 
292
- normalized_comment = String.new(encoding: text.encoding) << normalize_comment_lines(comment_lines).join("\n")
293
- [normalized_comment, directives]
294
- end
297
+ # Remove preceding indent spaces and blank lines from the comment lines
298
+
299
+ private def normalize_comment_lines(lines)
300
+ blank_line_regexp = /\A\s*\z/
301
+ lines = lines.dup
302
+ lines.shift while lines.first&.match?(blank_line_regexp)
303
+ lines.pop while lines.last&.match?(blank_line_regexp)
295
304
 
296
- # Remove preceding indent spaces and blank lines from the comment lines
297
-
298
- private def normalize_comment_lines(lines)
299
- blank_line_regexp = /\A\s*\z/
300
- lines = lines.dup
301
- lines.shift while lines.first&.match?(blank_line_regexp)
302
- lines.pop while lines.last&.match?(blank_line_regexp)
303
-
304
- min_spaces = lines.map do |l|
305
- l.match(/\A *(?=\S)/)&.end(0)
306
- end.compact.min
307
- if min_spaces && min_spaces > 0
308
- lines.map { |l| l[min_spaces..] || '' }
309
- else
310
- lines
305
+ min_spaces = lines.map do |l|
306
+ l.match(/\A *(?=\S)/)&.end(0)
307
+ end.compact.min
308
+ if min_spaces && min_spaces > 0
309
+ lines.map { |l| l[min_spaces..] || '' }
310
+ else
311
+ lines
312
+ end
311
313
  end
312
- end
313
314
 
314
- # Take value lines of multiline directive
315
+ # Take value lines of multiline directive
315
316
 
316
- private def take_multiline_directive_value_lines(directive, filename, line_no, lines, base_indent_size, indent_regexp, has_param)
317
- return [] if lines.empty?
317
+ private def take_multiline_directive_value_lines(directive, filename, line_no, lines, base_indent_size, indent_regexp, has_param)
318
+ return [] if lines.empty?
318
319
 
319
- first_indent_size = lines.first.match(indent_regexp).end(0)
320
+ first_indent_size = lines.first.match(indent_regexp).end(0)
320
321
 
321
- # Blank line or unindented line is not part of multiline-directive value
322
- return [] if first_indent_size <= base_indent_size
322
+ # Blank line or unindented line is not part of multiline-directive value
323
+ return [] if first_indent_size <= base_indent_size
323
324
 
324
- if has_param
325
- # :multiline-directive: line1
326
- # line2
327
- # line3
328
- #
329
- value_lines = lines.take_while do |l|
330
- l.rstrip.match(indent_regexp).end(0) > base_indent_size
331
- end
332
- min_indent = value_lines.map { |l| l.match(indent_regexp).end(0) }.min
333
- value_lines.map { |l| l[min_indent..] }
334
- else
335
- # Take indented lines accepting blank lines between them
336
- value_lines = lines.take_while do |l|
337
- l = l.rstrip
338
- indent = l[indent_regexp]
339
- if indent == l || indent.size >= first_indent_size
340
- true
325
+ if has_param
326
+ # :multiline-directive: line1
327
+ # line2
328
+ # line3
329
+ #
330
+ value_lines = lines.take_while do |l|
331
+ l.rstrip.match(indent_regexp).end(0) > base_indent_size
341
332
  end
342
- end
343
- value_lines.map! { |l| (l[first_indent_size..] || '').chomp }
333
+ min_indent = value_lines.map { |l| l.match(indent_regexp).end(0) }.min
334
+ value_lines.map { |l| l[min_indent..] }
335
+ else
336
+ # Take indented lines accepting blank lines between them
337
+ value_lines = lines.take_while do |l|
338
+ l = l.rstrip
339
+ indent = l[indent_regexp]
340
+ if indent == l || indent.size >= first_indent_size
341
+ true
342
+ end
343
+ end
344
+ value_lines.map! { |l| (l[first_indent_size..] || '').chomp }
344
345
 
345
- if value_lines.size != lines.size && !value_lines.last.empty?
346
- warn "#{filename}:#{line_no} Multiline directive :#{directive}: should end with a blank line."
346
+ if value_lines.size != lines.size && !value_lines.last.empty?
347
+ warn "#{filename}:#{line_no} Multiline directive :#{directive}: should end with a blank line."
348
+ end
349
+ value_lines.pop while value_lines.last&.empty?
350
+ value_lines
347
351
  end
348
- value_lines.pop while value_lines.last&.empty?
349
- value_lines
350
352
  end
351
353
  end
352
354
  end