yard-markdown 0.6.0 → 0.7.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.
@@ -1,6 +1,348 @@
1
- module Yard
1
+ # Namespace for YARD extensions used by this gem.
2
+ module YARD
3
+ # Shared helpers for rendering YARD objects as Markdown.
2
4
  module Markdown
3
- VERSION: String
4
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
5
+ # Computes anchor ids that match the generated Markdown headings.
6
+ module ArefHelper
7
+ include YARD::Markdown::AnchorComponentHelper
8
+
9
+ # Returns the primary anchor id for a documented object.
10
+ #
11
+ # _@param_ `object` — Object being rendered.
12
+ #
13
+ # _@return_ — Anchor id for the object's heading.
14
+ def aref: (Object object) -> String
15
+
16
+ # Encodes a value so it can be embedded safely in an HTML anchor id.
17
+ #
18
+ # _@param_ `value` — Raw anchor fragment to encode.
19
+ #
20
+ # _@return_ — Anchor-safe identifier fragment.
21
+ def anchor_component: () -> String
22
+ end
23
+
24
+ # Builds headings and legacy anchors for rendered object sections.
25
+ module HeadingHelper
26
+ include YARD::Markdown::ArefHelper
27
+
28
+ # Returns the legacy YARD anchor for an object when one exists.
29
+ #
30
+ # _@param_ `object` — Object being rendered.
31
+ #
32
+ # _@return_ — Legacy anchor id, if supported.
33
+ def legacy_aref: (Object object) -> String?
34
+
35
+ # Returns all anchor tags that should be attached to a heading.
36
+ #
37
+ # _@param_ `object` — Object being rendered.
38
+ #
39
+ # _@return_ — HTML anchor tags for the object.
40
+ def anchor_tags_for: (Object object) -> Symbol
41
+
42
+ # Appends the generated anchor tags to a Markdown heading.
43
+ #
44
+ # _@param_ `heading` — Heading text to decorate.
45
+ #
46
+ # _@param_ `object` — Object being rendered.
47
+ #
48
+ # _@return_ — Heading text with embedded anchor tags.
49
+ def heading_with_anchors: (String heading, Object object) -> String
50
+
51
+ # Builds an HTML anchor tag for a generated id.
52
+ #
53
+ # _@param_ `id` — Anchor id value.
54
+ #
55
+ # _@return_ — HTML anchor tag.
56
+ def anchor_tag: (String id) -> String
57
+
58
+ # Returns the primary anchor id for a documented object.
59
+ #
60
+ # _@param_ `object` — Object being rendered.
61
+ #
62
+ # _@return_ — Anchor id for the object's heading.
63
+ def aref: () -> String
64
+
65
+ # Encodes a value so it can be embedded safely in an HTML anchor id.
66
+ #
67
+ # _@param_ `value` — Raw anchor fragment to encode.
68
+ #
69
+ # _@return_ — Anchor-safe identifier fragment.
70
+ def anchor_component: () -> String
71
+ end
72
+
73
+ # Converts YARD docstrings into Markdown-friendly text.
74
+ module DocumentationHelper
75
+ # Returns the rendered documentation text for an object.
76
+ #
77
+ # _@param_ `object` — Object whose docstring is being rendered.
78
+ #
79
+ # _@return_ — Converted documentation text or a fallback message.
80
+ def documented_text: (Object object) -> String
81
+
82
+ # Converts an RDoc-formatted docstring to Markdown.
83
+ #
84
+ # _@param_ `docstring` — Raw docstring content.
85
+ #
86
+ # _@return_ — Markdown-rendered docstring content.
87
+ def rdoc_to_md: (Object docstring) -> String
88
+ end
89
+
90
+ # Collects and sorts the objects shown on a rendered object page.
91
+ module ObjectListingHelper
92
+ # Returns the constants and class variables defined on an object.
93
+ #
94
+ # _@param_ `object` — Object being rendered.
95
+ #
96
+ # _@return_ — Constants and class variables.
97
+ def constant_listing: (Object object) -> Symbol
98
+
99
+ # Returns the visible public methods defined directly on an object.
100
+ #
101
+ # _@param_ `object` — Object being rendered.
102
+ #
103
+ # _@return_ — Sorted public methods.
104
+ def public_method_list: (Object object) -> Symbol
105
+
106
+ # Returns the public class methods defined directly on an object.
107
+ #
108
+ # _@param_ `object` — Object being rendered.
109
+ #
110
+ # _@return_ — Sorted public class methods.
111
+ def public_class_methods: (Object object) -> Symbol
112
+
113
+ # Returns the public instance methods defined directly on an object.
114
+ #
115
+ # _@param_ `object` — Object being rendered.
116
+ #
117
+ # _@return_ — Sorted public instance methods.
118
+ def public_instance_methods: (Object object) -> Symbol
119
+
120
+ # Returns the visible attribute methods for an object.
121
+ #
122
+ # _@param_ `object` — Object being rendered.
123
+ #
124
+ # _@return_ — Sorted attribute methods.
125
+ def attr_listing: (Object object) -> Symbol
126
+
127
+ # Sorts a listing by scope and case-insensitive name.
128
+ #
129
+ # _@param_ `list` — Objects to sort.
130
+ #
131
+ # _@return_ — Sorted objects.
132
+ def sort_listing: (Symbol list) -> Symbol
133
+
134
+ # Returns whether an object is explicitly hidden with `:nodoc:`.
135
+ #
136
+ # _@param_ `object` — Listed object whose docstring may start with `:nodoc:`.
137
+ #
138
+ # _@return_ — True when the object should be hidden.
139
+ def hidden_object?: (Object object) -> bool
140
+ end
141
+
142
+ # Formats YARD tags into Markdown list items and fenced examples.
143
+ module TagFormattingHelper
144
+ # Renders all tags for an object as Markdown.
145
+ #
146
+ # _@param_ `object` — Object whose tags are being rendered.
147
+ #
148
+ # _@return_ — Markdown representation of the object's tags.
149
+ def render_tags: (Object object) -> String
150
+
151
+ # Formats a non-example YARD tag as a Markdown list item body.
152
+ #
153
+ # _@param_ `tag` — Non-example tag being converted into list item text.
154
+ #
155
+ # _@return_ — Markdown representation of the tag.
156
+ def format_tag: (Object tag) -> String
157
+
158
+ # Normalizes tag type declarations into printable strings.
159
+ #
160
+ # _@param_ `types` — Raw tag types from YARD.
161
+ #
162
+ # _@return_ — Cleaned type strings.
163
+ def normalized_tag_types: (Symbol? types) -> Symbol
164
+
165
+ # Formats a hash-style tag type entry.
166
+ #
167
+ # _@param_ `name` — Type name to format.
168
+ #
169
+ # _@param_ `value` — Associated type detail.
170
+ #
171
+ # _@return_ — Formatted type entry, or nil when blank.
172
+ def format_hash_tag_type: (String name, Object value) -> String?
173
+ end
174
+
175
+ # Builds anchor-safe identifier fragments from arbitrary values.
176
+ module AnchorComponentHelper
177
+ # Encodes a value so it can be embedded safely in an HTML anchor id.
178
+ #
179
+ # _@param_ `value` — Raw anchor fragment to encode.
180
+ #
181
+ # _@return_ — Anchor-safe identifier fragment.
182
+ def anchor_component: (Object value) -> String
183
+ end
184
+
185
+ # Assembles grouped content into ordered Markdown sections.
186
+ module SectionAssemblyHelper
187
+ # Groups items by their YARD group and orders them for rendering.
188
+ #
189
+ # _@param_ `items` — Renderable objects that expose a YARD group name.
190
+ #
191
+ # _@param_ `group_order` — Preferred ordering for named groups.
192
+ #
193
+ # _@return_ — Ordered pairs of group names and grouped items.
194
+ def grouped_items: (Symbol items, Symbol? group_order) -> Symbol
195
+
196
+ # Appends non-empty content to a mutable list of lines.
197
+ #
198
+ # _@param_ `lines` — Destination line buffer.
199
+ #
200
+ # _@param_ `content` — Rendered Markdown block to split into lines.
201
+ #
202
+ # _@param_ `separated` — Whether to insert a blank separator line first.
203
+ def append_lines: (Symbol lines, String content, ?separated: bool) -> void
204
+ end
205
+
206
+ # Rewrites generated Markdown links so they point at Markdown output.
207
+ module LinkNormalizationHelper
208
+ # Normalizes generated Markdown before it is written to disk.
209
+ #
210
+ # _@param_ `content` — Markdown content to finalize.
211
+ #
212
+ # _@param_ `current_path` — Output path for the current document.
213
+ #
214
+ # _@return_ — Normalized Markdown content with a trailing newline.
215
+ def finalize_markdown: ((String | Symbol) content, String current_path) -> String
216
+
217
+ # Rewrites local Markdown links relative to the current output path.
218
+ #
219
+ # _@param_ `markdown` — Markdown content to rewrite.
220
+ #
221
+ # _@param_ `current_path` — Output path for the current document.
222
+ #
223
+ # _@return_ — Markdown with local links normalized.
224
+ def normalize_local_links: (String markdown, String current_path) -> String
225
+
226
+ # Resolves a local link path to a YARD registry object when possible.
227
+ #
228
+ # _@param_ `path` — Link target path to resolve.
229
+ #
230
+ # _@param_ `current_dir` — Directory for the current output file.
231
+ #
232
+ # _@return_ — Matched registry object, if any.
233
+ def resolve_registry_object: (String path, Pathname current_dir) -> Object?
234
+
235
+ # Resolves a local link target to the final relative Markdown path.
236
+ #
237
+ # _@param_ `path` — Link target path to resolve.
238
+ #
239
+ # _@param_ `current_dir` — Directory for the current output file.
240
+ #
241
+ # _@return_ — Relative Markdown path, or nil when unresolved.
242
+ def resolve_local_link_target: (String path, Pathname current_dir) -> String?
243
+
244
+ # Returns whether a path looks like a constant reference.
245
+ #
246
+ # _@param_ `value` — Link target to inspect.
247
+ #
248
+ # _@return_ — True when the path resembles a constant name.
249
+ def constant_reference_path?: (String value) -> bool
250
+
251
+ # Returns whether a path looks like an unresolved bare identifier.
252
+ #
253
+ # _@param_ `path` — Link target to inspect.
254
+ #
255
+ # _@return_ — True when the target should be treated as unresolved.
256
+ def unresolved_identifier_target?: (String path) -> bool
257
+
258
+ # Computes a relative path from the current output directory.
259
+ #
260
+ # _@param_ `current_dir` — Directory for the current output file.
261
+ #
262
+ # _@param_ `target_path` — Output path being linked to.
263
+ #
264
+ # _@return_ — Relative path suitable for a Markdown link.
265
+ def relative_output_path: (Pathname current_dir, (String | Pathname) target_path) -> String
266
+
267
+ # Replaces malformed local Markdown links with inline code.
268
+ #
269
+ # _@param_ `markdown` — Markdown content to normalize.
270
+ #
271
+ # _@return_ — Markdown with malformed local links replaced.
272
+ def normalize_malformed_local_links: (String markdown) -> String
273
+ end
274
+
275
+ # Formats method and attribute names for Markdown headings.
276
+ module MethodPresentationHelper
277
+ # Builds the display heading for a method.
278
+ #
279
+ # _@param_ `method_object` — Method being rendered.
280
+ #
281
+ # _@return_ — Method heading text.
282
+ def formatted_method_heading: (Object method_object) -> String
283
+
284
+ # Returns the rendered parameter list for a method.
285
+ #
286
+ # _@param_ `method_object` — Method being rendered.
287
+ #
288
+ # _@return_ — Parenthesized method signature.
289
+ def method_signature: (Object method_object) -> String
290
+
291
+ # Returns the access marker for an attribute.
292
+ #
293
+ # _@param_ `attribute` — Attribute reader or writer.
294
+ #
295
+ # _@return_ — Access mode marker such as `R`, `W`, or `RW`.
296
+ def attribute_access: (Object attribute) -> String
297
+ end
298
+
299
+ # Renders grouped Markdown sections for constants, attributes, and methods.
300
+ module CollectionRenderingHelper
301
+ # Renders the constants section for an object page.
302
+ #
303
+ # _@param_ `constants` — Constant objects collected for the current page.
304
+ #
305
+ # _@param_ `group_order` — Preferred ordering for group headings.
306
+ #
307
+ # _@return_ — Markdown for the constants section.
308
+ def render_constants: (Symbol constants, Symbol? group_order) -> String
309
+
310
+ # Renders the attributes section for an object page.
311
+ #
312
+ # _@param_ `attrs` — Attributes to render.
313
+ #
314
+ # _@param_ `group_order` — Preferred ordering for group headings.
315
+ #
316
+ # _@return_ — Markdown for the attributes section.
317
+ def render_attributes: (Symbol attrs, Symbol? group_order) -> String
318
+
319
+ # Renders a method section for an object page.
320
+ #
321
+ # _@param_ `section_title` — Section title to render.
322
+ #
323
+ # _@param_ `methods` — Method objects collected for the current section.
324
+ #
325
+ # _@param_ `group_order` — Preferred ordering for group headings.
326
+ #
327
+ # _@return_ — Markdown for the method section.
328
+ def render_methods: (String section_title, Symbol methods, Symbol? group_order) -> String
329
+ end
330
+
331
+ # Renders inheritance and mixin relationship summaries.
332
+ module RelationshipSectionHelper
333
+ # Returns section content with the expected trailing spacing.
334
+ #
335
+ # _@param_ `content` — Section content to render.
336
+ #
337
+ # _@return_ — Section content followed by blank-line spacing.
338
+ def render_section_content: (Object content) -> String
339
+
340
+ # Returns inheritance and mixin relationships for an object.
341
+ #
342
+ # _@param_ `object` — Object being rendered.
343
+ #
344
+ # _@return_ — Markdown summary of the object's relationships.
345
+ def object_relationships: (Object object) -> String
346
+ end
5
347
  end
6
- end
348
+ end
@@ -1,20 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'csv'
3
+ require "csv"
4
4
 
5
- include Helpers::ModuleHelper
5
+ class_eval do
6
+ include YARD::Templates::Helpers::ModuleHelper
7
+ include YARD::Markdown::ArefHelper
8
+ include YARD::Markdown::ObjectListingHelper
9
+ end
6
10
 
11
+ # Prepares the markdown serializer and renders each object page.
12
+ #
13
+ # @return [void]
7
14
  def init
8
15
  options.objects = objects = run_verifier(options.objects).reject { |item| item.name == :root }
9
16
 
10
17
  options.delete(:objects)
11
18
  options.delete(:files)
12
19
 
13
- options.serializer.extension = 'md'
20
+ options.serializer.extension = "md"
14
21
 
15
22
  objects.each do |object|
16
23
  Templates::Engine.with_serializer(object, options.serializer) { serialize(object) }
17
- rescue StandardError => e
24
+ rescue => e
18
25
  path = options.serializer.serialized_path(object)
19
26
  log.error "Exception occurred while generating '#{path}'"
20
27
  log.backtrace(e)
@@ -23,23 +30,31 @@ def init
23
30
  serialize_index(objects)
24
31
  end
25
32
 
33
+ # Renders the markdown template for a single namespace object.
34
+ #
35
+ # @param object [YARD::CodeObjects::NamespaceObject] Object whose page will be serialized.
36
+ # @return [String] Rendered markdown for the object.
26
37
  def serialize(object)
27
- T('module').run(options.merge(object: object))
38
+ T("module").run(options.merge(object: object))
28
39
  end
29
40
 
41
+ # Writes the CSV search index for all rendered objects.
42
+ #
43
+ # @param objects [Array<YARD::CodeObjects::NamespaceObject>] Verified objects included in the generated documentation.
44
+ # @return [void]
30
45
  def serialize_index(objects)
31
46
  filepath = "#{options.serializer.basepath}/index.csv"
32
47
 
33
- CSV.open(filepath, 'wb') do |csv|
48
+ CSV.open(filepath, "wb") do |csv|
34
49
  csv << %w[name type path]
35
50
 
36
51
  objects.each do |object|
37
52
  next if object.name == :root
38
53
 
39
54
  if object.type == :class
40
- csv << [object.path, 'Class', options.serializer.serialized_path(object)]
55
+ csv << [object.path, "Class", options.serializer.serialized_path(object)]
41
56
  elsif object.type == :module
42
- csv << [object.path, 'Module', options.serializer.serialized_path(object)]
57
+ csv << [object.path, "Module", options.serializer.serialized_path(object)]
43
58
  end
44
59
 
45
60
  constants = constant_listing(object)
@@ -47,8 +62,8 @@ def serialize_index(objects)
47
62
  constants.each do |cnst|
48
63
  csv << [
49
64
  "#{object.path}.#{cnst.name(false)}",
50
- 'Constant',
51
- (options.serializer.serialized_path(object) + '#' + aref(cnst))
65
+ "Constant",
66
+ (options.serializer.serialized_path(object) + "#" + aref(cnst))
52
67
  ]
53
68
  end
54
69
  end
@@ -57,8 +72,8 @@ def serialize_index(objects)
57
72
  insmeths.each do |item|
58
73
  csv << [
59
74
  "#{object.path}.#{item.name(false)}",
60
- 'Method',
61
- options.serializer.serialized_path(object) + '#' + aref(item)
75
+ "Method",
76
+ options.serializer.serialized_path(object) + "#" + aref(item)
62
77
  ]
63
78
  end
64
79
  end
@@ -67,8 +82,8 @@ def serialize_index(objects)
67
82
  pubmeths.each do |item|
68
83
  csv << [
69
84
  "#{object.path}.#{item.name(false)}",
70
- 'Method',
71
- options.serializer.serialized_path(object) + '#' + aref(item)
85
+ "Method",
86
+ options.serializer.serialized_path(object) + "#" + aref(item)
72
87
  ]
73
88
  end
74
89
  end
@@ -78,79 +93,10 @@ def serialize_index(objects)
78
93
  attrs.each do |item|
79
94
  csv << [
80
95
  "#{object.path}.#{item.name(false)}",
81
- 'Attribute',
82
- options.serializer.serialized_path(object) + '#' + aref(item)
96
+ "Attribute",
97
+ options.serializer.serialized_path(object) + "#" + aref(item)
83
98
  ]
84
99
  end
85
100
  end
86
101
  end
87
102
  end
88
-
89
- def aref(object)
90
- type = object.type
91
-
92
- return "class-#{anchor_component(object.path.gsub('::', '-'))}" if type == :class
93
- return "module-#{anchor_component(object.path.gsub('::', '-'))}" if type == :module
94
- return "constant-#{anchor_component(object.name(false))}" if type == :constant
95
- return "classvariable-#{anchor_component(object.name(false))}" if type == :classvariable
96
-
97
- scope = object.scope == :class ? 'c' : 'i'
98
-
99
- if object.respond_to?(:attr_info) && !object.attr_info.nil?
100
- "attribute-#{scope}-#{anchor_component(object.name(false))}"
101
- else
102
- "method-#{scope}-#{anchor_component(object.name(false))}"
103
- end
104
- end
105
-
106
- def anchor_component(value)
107
- value.to_s.each_char.map do |char|
108
- char.match?(/[A-Za-z0-9_-]/) ? char : format('-%X', char.ord)
109
- end.join
110
- end
111
-
112
- def constant_listing(object)
113
- constants = object.constants(included: false, inherited: false)
114
- constants + object.cvars
115
- end
116
-
117
- def public_method_list(object)
118
- prune_method_listing(
119
- object.meths(inherited: false, visibility: [:public]),
120
- included: false
121
- ).reject { |item| hidden_object?(item) }
122
- .sort_by { |m| m.name.to_s }
123
- end
124
-
125
- def public_class_methods(object)
126
- public_method_list(object).select { |o| o.scope == :class }
127
- end
128
-
129
- def public_instance_methods(object)
130
- public_method_list(object).select { |o| o.scope == :instance }
131
- end
132
-
133
- def attr_listing(object)
134
- attrs = []
135
- object.inheritance_tree(true).each do |superclass|
136
- next if superclass.is_a?(CodeObjects::Proxy)
137
- next if !options.embed_mixins.empty? && !options.embed_mixins_match?(superclass)
138
-
139
- %i[class instance].each do |scope|
140
- superclass.attributes[scope].each do |_name, rw|
141
- attr = prune_method_listing([rw[:read], rw[:write]].compact, false).first
142
- attrs << attr if attr
143
- end
144
- end
145
- break if options.embed_mixins.empty?
146
- end
147
- sort_listing(attrs)
148
- end
149
-
150
- def sort_listing(list)
151
- list.sort_by { |o| [o.scope.to_s, o.name.to_s.downcase] }
152
- end
153
-
154
- def hidden_object?(object)
155
- object.docstring.to_s.strip.start_with?(':nodoc:')
156
- end