yard-markdown 0.8.0 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9d0f4cb4021498fef4a2ae549af15357c6d2fa65e2099677e75d1b25920e680
4
- data.tar.gz: 465def23d344679e869e776d856ce5a694e483d46dc5ab37fcf43eebe67f11cf
3
+ metadata.gz: 80c8051a8c7527055a46d9dcad2db56a019f54bb99315e25813a010152fd2df3
4
+ data.tar.gz: 7187cf79b4ea2ef53b859cb17971681eefc3981e2d3da9718dead415a2b503f2
5
5
  SHA512:
6
- metadata.gz: c2c2c4b64ea40ec28ab122d2398f2cfc72823e35fbb6a50a16146b5cb5199c44df4431cd568c00917d1011812afdb6c2c4d5862eaa8a2e66a3288bb9a901b731
7
- data.tar.gz: 63d188cab16ac36c3200205a01a0dd8f902061db68d2fdbc0ab81357de96cb478e44ae066e2ecd439978cba25c9ab60576aa385c0c496e32e9b3eec142de5e26
6
+ metadata.gz: 71b9f9638c8f7da302a2d8a412524bef3bb77aa7a0ec5f38a8cdc45fa04f4a65e34b0d6e7bb9c0b42e765c474041ec6b9a2845d7136f11552dd64e6f4fc52720
7
+ data.tar.gz: 6e1459ddb1e780dc708d67a1bc13d8f7315bfd8041a07c72207bf66af6bf4d9b91ce9833d7346ec78eef2708eff449932bb6d2743d4e64b8ea5bfe87d3d71e4a
data/CHANGELOG.md CHANGED
@@ -5,6 +5,14 @@ This format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
5
5
 
6
6
  ## Unreleased
7
7
 
8
+ ## 0.9.1
9
+
10
+ - Include full filenames for files, not just titles
11
+
12
+ ## 0.9.0
13
+
14
+ - Detect Markdown files, copy them into generated documentation, and include them in `index.csv`.
15
+
8
16
  ## 0.8.0
9
17
 
10
18
  - Adding metadata section
data/README.md CHANGED
@@ -19,6 +19,16 @@ gem install yard-markdown
19
19
 
20
20
  Run `yardoc --format=markdown` to generate markdown documentation.
21
21
 
22
+ Markdown files in the project tree are detected automatically, copied unchanged into the output, and listed in `index.csv`:
23
+
24
+ Markdown files whose basename starts with `_` are ignored automatically.
25
+
26
+ Use YARD's `--exclude` option to omit a separate documentation tree:
27
+
28
+ ```bash
29
+ yardoc --format=markdown --exclude '\Adocs/'
30
+ ```
31
+
22
32
  ## FAQ
23
33
 
24
34
  ### Note on RDoc support
@@ -66,14 +76,14 @@ Validate generated markdown in sample docs:
66
76
  bundle exec rake markdown:validate_examples
67
77
  ```
68
78
 
69
- There is also a real-world validation harness for repositories with substantial YARD documentation (`rspec-core`, `sidekiq`):
79
+ There is also a real-world validation harness for repositories with substantial YARD documentation (`faraday`, `sidekiq`):
70
80
 
71
81
  ```bash
72
82
  bundle exec rake markdown:validate_real_world
73
83
  ```
74
84
 
75
- This task validates generated markdown against CommonMark + GFM rendering, and reports unresolved local links found in upstream source comments while still validating local anchor/link structure.
85
+ This task validates every generated Markdown file against CommonMark and GFM. Generated files must have valid local links and anchors; unresolved links and anchors in byte-identical Markdown copied from upstream are reported instead of failing validation.
76
86
 
77
- GitHub Actions CI now runs this task on every push/PR, so `sidekiq` and other real-world fixture gems are verified continuously.
87
+ GitHub Actions CI runs this task on every push/PR, so both real-world fixture gems are verified continuously.
78
88
 
79
- For reproducible checks, the task clones pinned tags (`rspec-core` `v3.13.2`, `sidekiq` `v7.3.10`) into `tmp/real-world/repos` before generating output.
89
+ For reproducible checks, the task clones pinned tags (`faraday` `v2.14.3`, `sidekiq` `v7.3.10`) into `tmp/real-world/repos` and honors each repository's `.yardopts` before generating output in `tmp/real-world/faraday` and `tmp/real-world/sidekiq`.
@@ -10,7 +10,7 @@ module YARD
10
10
  #
11
11
  # @param value [Object] Raw anchor fragment to encode.
12
12
  # @return [String] Anchor-safe identifier fragment.
13
- def anchor_component(value)
13
+ def self.anchor_component(value)
14
14
  value.to_s.each_char.map do |char|
15
15
  char.match?(/[A-Za-z0-9_-]/) ? char : format("-%X", char.ord)
16
16
  end.join
@@ -20,22 +20,41 @@ module YARD
20
20
  #
21
21
  # @param object [YARD::CodeObjects::Base] Object being rendered.
22
22
  # @return [String] Anchor id for the object's heading.
23
- def aref(object)
24
- type = object.type
25
-
26
- return "class-#{object.path.gsub("::", "-")}" if type == :class
27
- return "module-#{object.path.gsub("::", "-")}" if type == :module
28
- return "constant-#{object.name}" if type == :constant
29
- return "classvariable-#{anchor_component(object.name)}" if type == :classvariable
30
-
31
- scope = (object.scope == :class) ? "c" : "i"
23
+ def self.aref(object)
24
+ aref_for(object, object.type, object.name)
25
+ end
32
26
 
33
- if !object.attr_info.nil?
34
- "attribute-#{scope}-#{object.name}"
27
+ # Dispatches anchor formatting using preloaded object attributes.
28
+ #
29
+ # @param object [YARD::CodeObjects::Base] Object being rendered.
30
+ # @param type [Symbol] YARD object type.
31
+ # @param name [String, Symbol] Object name.
32
+ # @return [String] Anchor id for the object's heading.
33
+ def self.aref_for(object, type, name)
34
+ case type
35
+ when :class, :module
36
+ "#{type}-#{object.path.gsub("::", "-")}"
37
+ when :constant
38
+ "constant-#{name}"
39
+ when :classvariable
40
+ "classvariable-#{anchor_component(name)}"
35
41
  else
36
- "method-#{scope}-#{anchor_component(object.name)}"
42
+ callable_aref(object, name)
37
43
  end
38
44
  end
45
+ private_class_method :aref_for
46
+
47
+ # Returns the anchor id for a method or attribute.
48
+ #
49
+ # @param object [YARD::CodeObjects::MethodObject] Method or attribute being rendered.
50
+ # @param name [String, Symbol] Method or attribute name.
51
+ # @return [String] Anchor id for the callable object's heading.
52
+ def self.callable_aref(object, name)
53
+ scope = (object.scope == :class) ? "c" : "i"
54
+ kind, name = object.attr_info ? ["attribute", name] : ["method", anchor_component(name)]
55
+ "#{kind}-#{scope}-#{name}"
56
+ end
57
+ private_class_method :callable_aref
39
58
  end
40
59
  end
41
60
  end
@@ -10,7 +10,7 @@ module YARD
10
10
  # @param group_order [Array<String>, nil] Preferred ordering for group headings.
11
11
  # @return [String] Markdown for the constants section.
12
12
  def render_constants(constants, group_order)
13
- render_collection("Constants", constants.sort_by { |item| item.name }, group_order) { |item| "`#{item.name}`" }
13
+ render_collection("Constants", constants.sort_by(&:name), group_order) { |item| "`#{item.name}`" }
14
14
  end
15
15
 
16
16
  # Renders the attributes section for an object page.
@@ -19,7 +19,7 @@ module YARD
19
19
  # @param group_order [Array<String>, nil] Preferred ordering for group headings.
20
20
  # @return [String] Markdown for the attributes section.
21
21
  def render_attributes(attrs, group_order)
22
- render_collection("Attributes", attrs, group_order) { |item| "`#{item.name}` [#{attribute_access(item)}]" }
22
+ render_collection("Attributes", attrs, group_order) { |item| "`#{item.name}` [#{MethodPresentationHelper.attribute_access(item)}]" }
23
23
  end
24
24
 
25
25
  # Renders a method section for an object page.
@@ -29,7 +29,7 @@ module YARD
29
29
  # @param group_order [Array<String>, nil] Preferred ordering for group headings.
30
30
  # @return [String] Markdown for the method section.
31
31
  def render_methods(section_title, methods, group_order)
32
- render_collection(section_title, methods, group_order) { |item| "`#{formatted_method_heading(item)}`" }
32
+ render_collection(section_title, methods, group_order) { |item| "`#{MethodPresentationHelper.formatted_method_heading(item)}`" }
33
33
  end
34
34
 
35
35
  # Renders a grouped collection with a caller-provided item label.
@@ -37,25 +37,36 @@ module YARD
37
37
  # @param section_title [String] Section title to render.
38
38
  # @param items [Array<YARD::CodeObjects::Base>] Objects to group and render.
39
39
  # @param group_order [Array<String>, nil] Preferred ordering for group headings.
40
+ # @param label [Proc] Item-label renderer.
41
+ # @yieldparam item [YARD::CodeObjects::Base] Object whose label should be rendered.
40
42
  # @return [String] Markdown for the collection section.
41
- def render_collection(section_title, items, group_order)
42
- lines = ["## #{section_title}"]
43
- groups = grouped_items(items, group_order)
44
- uses_groups = groups.any? { |name, _items| !name.nil? }
45
- item_heading = uses_groups ? "####" : "###"
43
+ def render_collection(section_title, items, group_order, &label)
44
+ groups = SectionAssemblyHelper.grouped_items(items, group_order)
45
+ grouped = groups.any? { |name, _items| name }
46
+ body = groups.map do |name, group_items|
47
+ item_heading = grouped ? "####" : "###"
48
+ item_markdown = group_items.map { |item| render_collection_item(item_heading, item, &label) }.join("\n\n")
49
+ [("### #{name || "General"}" if grouped), item_markdown].compact
50
+ end
46
51
 
47
- groups.each do |group_name, group_items|
48
- lines << "### #{group_name || "General"}" if uses_groups
52
+ ["## #{section_title}", body].join("\n")
53
+ end
49
54
 
50
- lines << group_items.map { |item|
51
- item_lines = [heading_with_anchors("#{item_heading} #{yield(item)}", item)]
52
- append_lines(item_lines, documented_text(item), separated: false)
53
- append_lines(item_lines, render_tags(item), separated: false)
54
- item_lines.join("\n")
55
- }.join("\n\n")
56
- end
55
+ private
57
56
 
58
- lines.join("\n")
57
+ # Renders one collection item with documentation and tags.
58
+ #
59
+ # @param item_heading [String] Markdown heading prefix for the item.
60
+ # @param item [YARD::CodeObjects::Base] Object being rendered.
61
+ # @param label [Proc] Item-label renderer.
62
+ # @yieldparam item [YARD::CodeObjects::Base] Object whose label should be rendered.
63
+ # @return [String] Rendered item Markdown.
64
+ def render_collection_item(item_heading, item, &label)
65
+ [
66
+ heading_with_anchors(item_heading + " " + label.call(item), item),
67
+ documented_text(item),
68
+ TagFormattingHelper.render_tags(item)
69
+ ].reject(&:empty?).join("\n")
59
70
  end
60
71
  end
61
72
  end
@@ -13,9 +13,8 @@ module YARD
13
13
  def documented_text(object)
14
14
  text = rdoc_to_md(object.docstring)
15
15
  return text unless text.empty?
16
- return "" unless object.tags.empty?
17
16
 
18
- "Not documented."
17
+ object.tags.empty? ? "Not documented." : ""
19
18
  end
20
19
 
21
20
  # Converts an RDoc-formatted docstring to Markdown.
@@ -25,17 +24,35 @@ module YARD
25
24
  def rdoc_to_md(docstring)
26
25
  fenced_code_blocks = []
27
26
  placeholder = "YARD_MARKDOWN_FENCED_CODE_BLOCK_%d"
28
- content = docstring.gsub(/^```[^\n]*\n.*?^```[ \t]*$/m) do |block|
29
- fenced_code_blocks << block
30
- format(placeholder, fenced_code_blocks.length - 1)
31
- end
32
-
27
+ content = extract_fenced_code_blocks(docstring, fenced_code_blocks, placeholder)
33
28
  markdown = RDoc::Markup::ToMarkdown.new.convert(content).rstrip
34
- fenced_code_blocks.each_with_index do |block, index|
35
- markdown = markdown.sub(format(placeholder, index), block)
29
+ restore_fenced_code_blocks(markdown, fenced_code_blocks, placeholder)
30
+ end
31
+
32
+ private
33
+
34
+ # Replaces fenced blocks with placeholders before RDoc conversion.
35
+ #
36
+ # @param docstring [String] Raw documentation text.
37
+ # @param fenced_code_blocks [Array<String>] Destination for extracted blocks.
38
+ # @param placeholder [String] Placeholder format string.
39
+ # @return [String] Documentation with fenced blocks replaced.
40
+ def extract_fenced_code_blocks(docstring, fenced_code_blocks, placeholder)
41
+ docstring.gsub(/^```[^\n]*\n.*?^```[ \t]*$/m) do |block|
42
+ format(placeholder, fenced_code_blocks.push(block).length - 1)
36
43
  end
44
+ end
37
45
 
38
- markdown
46
+ # Restores fenced blocks after RDoc conversion.
47
+ #
48
+ # @param markdown [String] Converted Markdown text.
49
+ # @param fenced_code_blocks [Array<String>] Extracted fenced blocks.
50
+ # @param placeholder [String] Placeholder format string.
51
+ # @return [String] Markdown with fenced blocks restored.
52
+ def restore_fenced_code_blocks(markdown, fenced_code_blocks, placeholder)
53
+ fenced_code_blocks.each_with_index.reduce(markdown) do |text, (block, index)|
54
+ text.sub(format(placeholder, index), block)
55
+ end
39
56
  end
40
57
  end
41
58
  end
@@ -4,22 +4,21 @@ module YARD
4
4
  module Markdown
5
5
  # Builds headings and legacy anchors for rendered object sections.
6
6
  module HeadingHelper
7
- include ArefHelper
8
-
9
7
  # Returns the legacy YARD anchor for an object when one exists.
10
8
  #
11
9
  # @param object [YARD::CodeObjects::Base] Object being rendered.
12
10
  # @return [String, nil] Legacy anchor id, if supported.
13
- def legacy_aref(object)
14
- type = object.type
15
-
16
- return "#{object.name}-constant" if type == :constant
17
- return "#{object.name}-classvariable" if type == :classvariable
18
- return nil unless object.respond_to?(:scope)
19
-
20
- return "#{object.name}-class_method" if object.scope == :class
21
-
22
- "#{object.name}-instance_method"
11
+ def self.legacy_aref(object)
12
+ name = object.name
13
+
14
+ case object.type
15
+ when :constant
16
+ "#{name}-constant"
17
+ when :classvariable
18
+ "#{name}-classvariable"
19
+ when :method
20
+ "#{name}-#{(object.scope == :class) ? "class" : "instance"}_method"
21
+ end
23
22
  end
24
23
 
25
24
  # Returns all anchor tags that should be attached to a heading.
@@ -27,7 +26,7 @@ module YARD
27
26
  # @param object [YARD::CodeObjects::Base] Object being rendered.
28
27
  # @return [Array<String>] HTML anchor tags for the object.
29
28
  def anchor_tags_for(object)
30
- anchors = [aref(object), legacy_aref(object)].compact
29
+ anchors = [ArefHelper.aref(object), HeadingHelper.legacy_aref(object)].compact
31
30
  anchors.map { |id| anchor_tag(id) }
32
31
  end
33
32
 
@@ -10,12 +10,9 @@ module YARD
10
10
  # @param current_path [String] Output path for the current document.
11
11
  # @return [String] Normalized Markdown content with a trailing newline.
12
12
  def finalize_markdown(content, current_path)
13
- output = content.instance_of?(Array) ? content.join("\n") : content
14
- output = output.lines.map(&:rstrip).join("\n")
15
- output = normalize_local_links(output, current_path)
16
- output = normalize_malformed_local_links(output)
17
- output = output.gsub(/\n{3,}/, "\n\n").strip
18
- "#{output}\n"
13
+ LinkNormalizationHelper.finish_markdown(
14
+ normalize_local_links(LinkNormalizationHelper.normalize_lines(content), current_path)
15
+ )
19
16
  end
20
17
 
21
18
  # Rewrites local Markdown links relative to the current output path.
@@ -27,17 +24,7 @@ module YARD
27
24
  current_dir = Pathname.new(current_path).dirname
28
25
 
29
26
  markdown.gsub(%r{\[(.+?)\]\((?!https?://|mailto:|#)([^)\n]+)\)}) do
30
- label = Regexp.last_match(1)
31
- target = Regexp.last_match(2)
32
- path = target.sub(/[?#].*\z/, "")
33
- suffix = target[path.length..]
34
- rewritten_path = resolve_local_link_target(path, current_dir)
35
-
36
- if rewritten_path.nil?
37
- "`#{label.tr("`", "")}`"
38
- else
39
- "[#{label}](#{rewritten_path}#{suffix})"
40
- end
27
+ normalize_local_link(Regexp.last_match, current_dir)
41
28
  end
42
29
  end
43
30
 
@@ -46,28 +33,37 @@ module YARD
46
33
  # @param path [String] Link target path to resolve.
47
34
  # @param current_dir [Pathname] Directory for the current output file.
48
35
  # @return [YARD::CodeObjects::Base, nil] Matched registry object, if any.
49
- def resolve_registry_object(path, current_dir)
50
- cleaned = path.sub(%r{\A(?:(?:\.\./)+|\./)}, "")
51
- candidates = [path]
52
-
53
- if constant_reference_path?(cleaned)
54
- current_parts = current_dir.to_s.split("/").reject { |part| part.empty? || part == "." }
55
- target_parts = cleaned.split("/")
56
-
57
- current_parts.length.downto(0) do |depth|
58
- candidates << (current_parts.first(depth) + target_parts).join("::")
59
- end
60
- end
36
+ def self.resolve_registry_object(path, current_dir)
37
+ registry_candidates(path, current_dir)
38
+ .map { |candidate| Registry.at(candidate) }
39
+ .compact
40
+ .reject { |object| object.equal?(Registry.root) }
41
+ .first
42
+ end
61
43
 
62
- candidates.each do |candidate|
63
- obj = Registry.at(candidate)
64
- next if obj.nil? || obj.equal?(Registry.root)
44
+ # Returns registry paths that may match a local target.
45
+ #
46
+ # @param path [String] Link target path to resolve.
47
+ # @param current_dir [Pathname] Directory for the current output file.
48
+ # @return [Array<String>] Candidate registry paths in lookup order.
49
+ def self.registry_candidates(path, current_dir)
50
+ cleaned = path.sub(%r{\A(?:(?:\.\./)+|\./)}, "")
51
+ return [path] unless constant_reference_path?(cleaned)
65
52
 
66
- return obj
67
- end
53
+ namespaced_candidates(cleaned, current_dir)
54
+ end
68
55
 
69
- nil
56
+ # Expands a constant target through each enclosing namespace.
57
+ #
58
+ # @param cleaned [String] Target without relative path prefixes.
59
+ # @param current_dir [Pathname] Directory for the current output file.
60
+ # @return [Array<String>] Namespaced registry candidates.
61
+ def self.namespaced_candidates(cleaned, current_dir)
62
+ current_parts = current_dir.to_s.split("/").reject { |part| part.empty? || part == "." }
63
+ target_parts = cleaned.split("/")
64
+ current_parts.length.downto(0).map { |depth| (current_parts.first(depth) + target_parts).join("::") }
70
65
  end
66
+ private_class_method :registry_candidates, :namespaced_candidates
71
67
 
72
68
  # Resolves a local link target to the final relative Markdown path.
73
69
  #
@@ -76,29 +72,15 @@ module YARD
76
72
  # @return [String, nil] Relative Markdown path, or nil when unresolved.
77
73
  def resolve_local_link_target(path, current_dir)
78
74
  normalized = path.sub(%r{\A/+}, "")
79
-
80
- obj = resolve_registry_object(normalized, current_dir)
81
- if obj
82
- object_path = options.serializer.serialized_path(obj)
83
- return relative_output_path(current_dir, object_path)
84
- end
85
-
86
- if normalized.match?(/\.html\z/i)
87
- normalized = normalized.sub(/\.html\z/i, ".md")
88
- elsif File.extname(normalized).empty?
89
- return nil if unresolved_identifier_target?(normalized)
90
-
91
- normalized = "#{normalized}.md" if normalized.include?("/")
92
- end
93
-
94
- relative_output_path(current_dir, normalized)
75
+ target = registry_path(normalized, current_dir) || copied_path(normalized) || LinkNormalizationHelper.markdown_path(normalized)
76
+ LinkNormalizationHelper.relative_output_path(current_dir, target) if target
95
77
  end
96
78
 
97
79
  # Returns whether a path looks like a constant reference.
98
80
  #
99
81
  # @param value [String] Link target to inspect.
100
82
  # @return [Boolean] True when the path resembles a constant name.
101
- def constant_reference_path?(value)
83
+ def self.constant_reference_path?(value)
102
84
  parts = value.split(%r{::|/}).reject(&:empty?)
103
85
  return false if parts.empty?
104
86
 
@@ -109,11 +91,9 @@ module YARD
109
91
  #
110
92
  # @param path [String] Link target to inspect.
111
93
  # @return [Boolean] True when the target should be treated as unresolved.
112
- def unresolved_identifier_target?(path)
94
+ def self.unresolved_identifier_target?(path)
113
95
  cleaned = path.sub(%r{\A(?:(?:\.\./)+|\./)}, "")
114
- return true if cleaned.start_with?(":") || cleaned.match?(/\A\d/)
115
-
116
- cleaned.match?(/\A[a-z_]\w*\z/)
96
+ File.extname(cleaned).empty? && !cleaned.include?("/")
117
97
  end
118
98
 
119
99
  # Computes a relative path from the current output directory.
@@ -121,7 +101,7 @@ module YARD
121
101
  # @param current_dir [Pathname] Directory for the current output file.
122
102
  # @param target_path [String, Pathname] Output path being linked to.
123
103
  # @return [String] Relative path suitable for a Markdown link.
124
- def relative_output_path(current_dir, target_path)
104
+ def self.relative_output_path(current_dir, target_path)
125
105
  target = target_path.to_s
126
106
  return target if target.start_with?("../")
127
107
 
@@ -130,12 +110,70 @@ module YARD
130
110
  target
131
111
  end
132
112
 
133
- # Replaces malformed local Markdown links with inline code.
113
+ # Converts supported content into normalized lines.
114
+ #
115
+ # @param content [String, Array<String>] Markdown content.
116
+ # @return [String] Joined content without trailing line whitespace.
117
+ def self.normalize_lines(content)
118
+ text = content.instance_of?(Array) ? content.join("\n") : content
119
+ text.lines.map(&:rstrip).join("\n")
120
+ end
121
+
122
+ # Compacts blank lines and adds the final newline.
123
+ #
124
+ # @param markdown [String] Normalized Markdown content.
125
+ # @return [String] Final Markdown content.
126
+ def self.finish_markdown(markdown)
127
+ "#{markdown.gsub(/\n{3,}/, "\n\n").strip}\n"
128
+ end
129
+
130
+ # Returns the Markdown output path for a non-registry target.
131
+ #
132
+ # @param path [String] Local link target.
133
+ # @return [String, nil] Markdown path, or nil for an unresolved identifier.
134
+ def self.markdown_path(path)
135
+ return path.sub(/\.html\z/i, ".md") if path.match?(/\.html\z/i)
136
+ return path unless File.extname(path).empty?
137
+ return if unresolved_identifier_target?(path)
138
+
139
+ "#{path}.md"
140
+ end
141
+
142
+ private
143
+
144
+ # Rewrites one matched local Markdown link.
145
+ #
146
+ # @param match [MatchData] Local link match.
147
+ # @param current_dir [Pathname] Directory for the current output file.
148
+ # @return [String] Rewritten link or code-formatted label.
149
+ def normalize_local_link(match, current_dir)
150
+ label, target = match.captures
151
+ path, separator, suffix = target.partition(/[?#]/)
152
+ rewritten_path = resolve_local_link_target(path, current_dir)
153
+ return "[#{label}](#{rewritten_path}#{separator}#{suffix})" if rewritten_path
154
+
155
+ "`#{label.tr("`", "")}`"
156
+ end
157
+
158
+ # Finds the serialized path for a registry object.
159
+ #
160
+ # @param path [String] Local link target.
161
+ # @param current_dir [Pathname] Directory for the current output file.
162
+ # @return [String, nil] Serialized object path, if resolved.
163
+ def registry_path(path, current_dir)
164
+ object = LinkNormalizationHelper.resolve_registry_object(path, current_dir)
165
+ return unless object
166
+
167
+ options.serializer.serialized_path(object)
168
+ end
169
+
170
+ # Finds a copied Markdown file by its normalized alias.
134
171
  #
135
- # @param markdown [String] Markdown content to normalize.
136
- # @return [String] Markdown with malformed local links replaced.
137
- def normalize_malformed_local_links(markdown)
138
- markdown.gsub(%r{\[([^\]]+)\]\((?!https?://|mailto:|#)(?:[^)\n]*['"][^)\n]*)\)}, '`\1`')
172
+ # @param path [String] Local link target.
173
+ # @return [String, nil] Copied file path, if registered.
174
+ def copied_path(path)
175
+ alias_path = Pathname.new(path.sub(/\.html\z/i, "")).cleanpath.to_s
176
+ options.copied_file_aliases[alias_path]
139
177
  end
140
178
  end
141
179
  end
@@ -9,21 +9,9 @@ module YARD
9
9
  # @param object [YARD::CodeObjects::NamespaceObject] Object being rendered.
10
10
  # @return [String] Markdown table containing the object's metadata.
11
11
  def object_metadata(object)
12
- rows = []
13
-
14
- if object.instance_of?(CodeObjects::ClassObject)
15
- rows << ["Inherits", metadata_reference(object.superclass)]
16
- end
17
-
18
- [[:class, "Extended by"], [:instance, "Includes"]].each do |scope, label|
19
- mixins = run_verifier(object.mixins(scope)).sort_by { |item| item.path }
20
- next if mixins.empty?
21
-
22
- rows << [label, mixins.map { |mixin| metadata_reference(mixin) }.join(", ")]
23
- end
24
-
25
- files = object.files.map(&:first).uniq
26
- rows << ["Defined in", files.map { |file| metadata_table_cell(file) }.join(", ")] unless files.empty?
12
+ superclass = object.superclass if object.instance_of?(CodeObjects::ClassObject)
13
+ rows = (superclass ? [["Inherits", metadata_reference(superclass)]] : []) +
14
+ mixin_rows(object) + MetadataSectionHelper.file_rows(object)
27
15
 
28
16
  return "" if rows.empty?
29
17
 
@@ -35,20 +23,57 @@ module YARD
35
23
  # @param target [YARD::CodeObjects::NamespaceObject, YARD::CodeObjects::Proxy] Referenced namespace.
36
24
  # @return [String] Markdown link or plain table-cell text.
37
25
  def metadata_reference(target)
38
- label = metadata_table_cell(target.path)
39
- return label unless target.is_a?(CodeObjects::Base) && run_verifier([target]).any?
26
+ path = target.path
27
+ label = MetadataSectionHelper.metadata_table_cell(path)
28
+ return label unless target.is_a?(CodeObjects::NamespaceObject) && run_verifier([target]).any?
40
29
 
41
- "[#{label}](#{target.path})"
30
+ "[#{label}](#{path})"
42
31
  end
43
32
 
44
33
  # Escapes text for a Markdown table cell.
45
34
  #
46
35
  # @param value [String] Metadata text.
47
36
  # @return [String] GFM table-safe Markdown text.
48
- def metadata_table_cell(value)
37
+ def self.metadata_table_cell(value)
49
38
  value.gsub(/[[:blank:]]*\R[[:blank:]]*/, " ")
50
39
  .gsub(/[\\|]/) { |character| "\\#{character}" }
51
40
  end
41
+
42
+ # Builds the source-file metadata rows.
43
+ #
44
+ # @param object [YARD::CodeObjects::NamespaceObject] Namespace being rendered.
45
+ # @return [Array<Array>] Source-file rows.
46
+ def self.file_rows(object)
47
+ files = object.files.map(&:first).uniq
48
+ return [] if files.empty?
49
+
50
+ [["Defined in", files.map { |file| metadata_table_cell(file) }.join(", ")]]
51
+ end
52
+
53
+ private
54
+
55
+ # Builds class and instance mixin rows.
56
+ #
57
+ # @param object [YARD::CodeObjects::NamespaceObject] Namespace being rendered.
58
+ # @return [Array<Array>] Visible mixin rows.
59
+ def mixin_rows(object)
60
+ [[:class, "Extended by"], [:instance, "Includes"]]
61
+ .map { |scope, label| mixin_row(object, scope, label) }
62
+ .compact
63
+ end
64
+
65
+ # Builds one scoped mixin row.
66
+ #
67
+ # @param object [YARD::CodeObjects::NamespaceObject] Namespace being rendered.
68
+ # @param scope [Symbol] Mixin scope.
69
+ # @param label [String] Metadata row label.
70
+ # @return [Array, nil] Mixin row, if visible mixins exist.
71
+ def mixin_row(object, scope, label)
72
+ mixins = run_verifier(object.mixins(scope)).sort_by(&:path)
73
+ return if mixins.empty?
74
+
75
+ [label, mixins.map { |mixin| metadata_reference(mixin) }.join(", ")]
76
+ end
52
77
  end
53
78
  end
54
79
  end
@@ -8,7 +8,7 @@ module YARD
8
8
  #
9
9
  # @param method_object [YARD::CodeObjects::MethodObject] Method being rendered.
10
10
  # @return [String] Method heading text.
11
- def formatted_method_heading(method_object)
11
+ def self.formatted_method_heading(method_object)
12
12
  name = method_object.name
13
13
  signature = method_signature(method_object)
14
14
  signature = " #{signature}" if name.end_with?("]")
@@ -19,11 +19,9 @@ module YARD
19
19
  #
20
20
  # @param method_object [YARD::CodeObjects::MethodObject] Method being rendered.
21
21
  # @return [String] Parenthesized method signature.
22
- def method_signature(method_object)
23
- return "()" if method_object.parameters.nil?
24
-
25
- rendered = method_object.parameters.map do |name, default|
26
- (default.nil? || default.empty?) ? name : "#{name} = #{default}"
22
+ def self.method_signature(method_object)
23
+ rendered = Array(method_object.parameters).map do |name, default|
24
+ default.to_s.empty? ? name : "#{name} = #{default}"
27
25
  end
28
26
 
29
27
  "(#{rendered.join(", ")})"
@@ -33,7 +31,7 @@ module YARD
33
31
  #
34
32
  # @param attribute [YARD::CodeObjects::MethodObject] Attribute reader or writer.
35
33
  # @return [String] Access mode marker such as `R`, `W`, or `RW`.
36
- def attribute_access(attribute)
34
+ def self.attribute_access(attribute)
37
35
  read, write = attribute.attr_info.fetch_values(:read, :write)
38
36
  return "RW" if read && write
39
37
  return "R" if read
@@ -8,7 +8,7 @@ module YARD
8
8
  #
9
9
  # @param object [YARD::CodeObjects::NamespaceObject] Object being rendered.
10
10
  # @return [Array<YARD::CodeObjects::Base>] Constants and class variables.
11
- def constant_listing(object)
11
+ def self.constant_listing(object)
12
12
  constants = object.constants(included: false, inherited: false)
13
13
  constants + object.cvars
14
14
  end
@@ -19,7 +19,7 @@ module YARD
19
19
  # @return [Array<YARD::CodeObjects::MethodObject>] Sorted public methods.
20
20
  def public_method_list(object)
21
21
  prune_method_listing(object.meths(inherited: false, visibility: :public))
22
- .reject { |item| hidden_object?(item) }
22
+ .reject { |item| ObjectListingHelper.hidden_object?(item) }
23
23
  .sort_by { |method_object| method_object.name }
24
24
  end
25
25
 
@@ -44,44 +44,50 @@ module YARD
44
44
  # @param object [YARD::CodeObjects::NamespaceObject] Object being rendered.
45
45
  # @return [Array<YARD::CodeObjects::MethodObject>] Sorted attribute methods.
46
46
  def attr_listing(object)
47
- attrs = []
48
-
49
- object.inheritance_tree(true).each do |superclass|
50
- next if !options.embed_mixins.empty? && !options.embed_mixins_match?(superclass)
51
-
52
- %i[class instance].each do |scope|
53
- superclass.attributes.fetch(scope).each do |_name, rw|
54
- attr = prune_method_listing([rw.fetch(:read), rw.fetch(:write)].compact, false).first
55
- attrs << attr if attr
56
- end
57
- end
58
-
59
- break if options.embed_mixins.empty?
60
- end
61
-
62
- sort_listing(attrs)
47
+ superclasses = attribute_superclasses(object)
48
+ attributes = superclasses.flat_map { |superclass| attributes_for(superclass) }
49
+ ObjectListingHelper.sort_attributes(attributes)
63
50
  end
64
51
 
65
- # Sorts a listing by scope and case-insensitive name.
52
+ # Sorts attributes by scope and case-insensitive name.
66
53
  #
67
- # @param list [Array<YARD::CodeObjects::Base>] Objects to sort.
68
- # @return [Array<YARD::CodeObjects::Base>] Sorted objects.
69
- def sort_listing(list)
70
- list.sort do |left, right|
71
- scope_comparison = left.scope <=> right.scope
72
- next scope_comparison unless scope_comparison.zero?
73
-
74
- left.name.to_s.casecmp(right.name.to_s)
75
- end
54
+ # @param attributes [Array<YARD::CodeObjects::MethodObject>] Attribute methods collected from eligible ancestors.
55
+ # @return [Array<YARD::CodeObjects::MethodObject>] Sorted attributes.
56
+ def self.sort_attributes(attributes)
57
+ attributes.sort { |left, right| (left.scope <=> right.scope).nonzero? || left.name.to_s.casecmp(right.name.to_s) }
76
58
  end
77
59
 
78
60
  # Returns whether an object is explicitly hidden with `:nodoc:`.
79
61
  #
80
62
  # @param object [YARD::CodeObjects::Base] Listed object whose docstring may start with `:nodoc:`.
81
63
  # @return [Boolean] True when the object should be hidden.
82
- def hidden_object?(object)
64
+ def self.hidden_object?(object)
83
65
  object.docstring.start_with?(":nodoc:")
84
66
  end
67
+
68
+ private
69
+
70
+ # Selects ancestors whose attributes should be embedded.
71
+ #
72
+ # @param object [YARD::CodeObjects::NamespaceObject] Namespace being rendered.
73
+ # @return [Array<YARD::CodeObjects::Base>] Eligible ancestors.
74
+ def attribute_superclasses(object)
75
+ superclasses = object.inheritance_tree(true)
76
+ return superclasses.first(1) if options.embed_mixins.empty?
77
+
78
+ superclasses.select { |superclass| options.embed_mixins_match?(superclass) }
79
+ end
80
+
81
+ # Collects visible attributes from one ancestor.
82
+ #
83
+ # @param superclass [YARD::CodeObjects::Base] Ancestor containing attributes.
84
+ # @return [Array<YARD::CodeObjects::MethodObject>] Visible attributes.
85
+ def attributes_for(superclass)
86
+ superclass.attributes.values.flat_map(&:values).map { |read_write|
87
+ read, write = read_write.fetch_values(:read, :write)
88
+ prune_method_listing([read, write].compact, false).first
89
+ }.compact
90
+ end
85
91
  end
86
92
  end
87
93
  end
@@ -8,7 +8,7 @@ module YARD
8
8
  #
9
9
  # @param content [Object] Section content to render.
10
10
  # @return [String] Section content followed by blank-line spacing.
11
- def render_section_content(content)
11
+ def self.render_section_content(content)
12
12
  text = content.to_s.strip
13
13
  return "" if text.empty?
14
14
 
@@ -20,27 +20,20 @@ module YARD
20
20
  # @param items [Array<#group>] Renderable objects that expose a YARD group name.
21
21
  # @param group_order [Array<String>, nil] Preferred ordering for named groups.
22
22
  # @return [Array<Array>] Ordered pairs of group names and grouped items.
23
- def grouped_items(items, group_order)
23
+ def self.grouped_items(items, group_order)
24
24
  groups = items.group_by(&:group)
25
- names = groups.keys
26
- order = Array(group_order)
27
- ordered_names = (order & names) + (names.compact - order).sort + ([nil] & names)
28
-
29
- ordered_names.map { |name| [name, groups.fetch(name)] }
25
+ ordered_group_names(groups.keys, Array(group_order)).map { |name| [name, groups.fetch(name)] }
30
26
  end
31
27
 
32
- # Appends non-empty content to a mutable list of lines.
28
+ # Orders known group names by configured, alphabetical, and default order.
33
29
  #
34
- # @param lines [Array<String>] Destination line buffer.
35
- # @param content [String] Rendered Markdown block to split into lines.
36
- # @param separated [Boolean] Whether to insert a blank separator line first.
37
- # @return [void]
38
- def append_lines(lines, content, separated: true)
39
- return if content.lstrip.empty?
40
-
41
- lines << "" if separated && !lines.empty? && !lines.last.empty?
42
- lines.concat(content.split("\n"))
30
+ # @param names [Array<String, nil>] Known group names.
31
+ # @param order [Array<String>] Preferred named-group order.
32
+ # @return [Array<String, nil>] Ordered group names.
33
+ def self.ordered_group_names(names, order)
34
+ (order & names) + (names.compact - order).sort + ([nil] & names)
43
35
  end
36
+ private_class_method :ordered_group_names
44
37
  end
45
38
  end
46
39
  end
@@ -8,43 +8,31 @@ module YARD
8
8
  #
9
9
  # @param object [YARD::CodeObjects::Base] Object whose tags are being rendered.
10
10
  # @return [String] Markdown representation of the object's tags.
11
- def render_tags(object)
11
+ def self.render_tags(object)
12
12
  example_tags, regular_tags = object.tags.partition { |tag| tag.tag_name == "example" }
13
- lines = regular_tags.map { |tag| "- #{format_tag(tag)}" }
14
-
15
- example_tags.each do |tag|
16
- lines << nil unless lines.empty?
17
- title = tag.name.to_s.rstrip.empty? ? "**@example**" : "**@example #{tag.name}**"
18
- lines << title
19
- lines << "```ruby"
20
- lines << tag.text.to_s.rstrip
21
- lines << "```"
13
+ regular = regular_tags.map { |tag| "- #{format_tag(tag)}" }.join("\n")
14
+ examples = example_tags.map do |tag|
15
+ name = tag.name.to_s.rstrip
16
+ title = name.empty? ? "**@example**" : "**@example #{name}**"
17
+ [title, "```ruby", tag.text.to_s.rstrip, "```"].join("\n")
22
18
  end
23
-
24
- lines.join("\n")
19
+ [regular, examples].reject(&:empty?).join("\n\n")
25
20
  end
26
21
 
27
22
  # Formats a non-example YARD tag as a Markdown list item body.
28
23
  #
29
24
  # @param tag [YARD::Tags::Tag] Non-example tag being converted into list item text.
30
25
  # @return [String] Markdown representation of the tag.
31
- def format_tag(tag)
32
- parts = ["**@#{tag.tag_name}**"]
33
- parts << "`#{tag.name}`" unless tag.name.to_s.lstrip.empty?
34
-
35
- cleaned_types = normalized_tag_types(tag.types)
36
- parts << "[#{cleaned_types.join(", ")}]" unless cleaned_types.empty?
37
- parts << tag.text.strip unless tag.text.to_s.lstrip.empty?
38
-
39
- parts.join(" ")
40
- end
41
-
42
- # Normalizes tag type declarations into printable strings.
43
- #
44
- # @param types [Array<Object>, nil] Raw tag types from YARD.
45
- # @return [Array<String>] Cleaned type strings.
46
- def normalized_tag_types(types)
47
- Array(types).map(&:to_s).map(&:strip).reject(&:empty?)
26
+ def self.format_tag(tag)
27
+ name = tag.name.to_s
28
+ text = tag.text.to_s
29
+ types = Array(tag.types).map { |type| type.to_s.strip }.reject(&:empty?)
30
+ [
31
+ "**@#{tag.tag_name}**",
32
+ ("`#{name}`" unless name.lstrip.empty?),
33
+ ("[#{types.join(", ")}]" unless types.empty?),
34
+ (text.strip unless text.lstrip.empty?)
35
+ ].compact.join(" ")
48
36
  end
49
37
  end
50
38
  end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YARD
4
+ module Markdown
5
+ # Discovers Markdown pages before YARD generates documentation.
6
+ module YardocExtension
7
+ private
8
+
9
+ # Adds Markdown pages to the files rendered by the Markdown template.
10
+ #
11
+ # @param checksums [Hash, nil] Previously generated file checksums.
12
+ # @return [void]
13
+ def run_generate(checksums)
14
+ add_extra_files(markdown_files) if options.format == :markdown
15
+
16
+ super
17
+ end
18
+
19
+ # Returns project Markdown files that YARD has not already discovered.
20
+ #
21
+ # @return [Array<String>] Markdown file paths to add.
22
+ def markdown_files
23
+ Dir.glob("**/*").grep(FILE_PATTERN)
24
+ .reject { |file| File.basename(file).start_with?("_") }
25
+ .reject { |file| excluded_file?(file) }
26
+ .reject { |file| output_file?(file) }
27
+ .reject { |file| existing_file?(file) }
28
+ end
29
+
30
+ # Returns whether a file matches a configured exclusion.
31
+ #
32
+ # @param file [String] Candidate file path.
33
+ # @return [Boolean] True when excluded.
34
+ def excluded_file?(file)
35
+ excluded.any? { |path| Regexp.new(path, Regexp::IGNORECASE).match?(file) }
36
+ end
37
+
38
+ # Returns whether a file is inside the output directory.
39
+ #
40
+ # @param file [String] Candidate file path.
41
+ # @return [Boolean] True when generated output would contain the file.
42
+ def output_file?(file)
43
+ output = File.expand_path(options.serializer.basepath)
44
+ File.expand_path(file).start_with?("#{output}/")
45
+ end
46
+
47
+ # Returns whether YARD has already discovered a file.
48
+ #
49
+ # @param file [String] Candidate file path.
50
+ # @return [Boolean] True when the file already exists in YARD options.
51
+ def existing_file?(file)
52
+ expanded_file = File.expand_path(file)
53
+ options.files.any? { |existing| File.expand_path(existing.filename) == expanded_file }
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YARD
4
+ module Markdown
5
+ # Matches supported Markdown file extensions.
6
+ FILE_PATTERN = /\.(?:md|markdown)\z/i
7
+ end
8
+ end
data/lib/yard-markdown.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "yard"
4
+ require_relative "yard/markdown"
4
5
  require_relative "yard/markdown/aref_helper"
5
6
  require_relative "yard/markdown/collection_rendering_helper"
6
7
  require_relative "yard/markdown/documentation_helper"
@@ -11,10 +12,7 @@ require_relative "yard/markdown/method_presentation_helper"
11
12
  require_relative "yard/markdown/object_listing_helper"
12
13
  require_relative "yard/markdown/section_assembly_helper"
13
14
  require_relative "yard/markdown/tag_formatting_helper"
14
-
15
- module YARD
16
- module Markdown
17
- end
18
- end
15
+ require_relative "yard/markdown/yardoc_extension"
19
16
 
20
17
  YARD::Templates::Engine.register_template_path File.dirname(__FILE__) + "/../templates"
18
+ YARD::CLI::Yardoc.prepend(YARD::Markdown::YardocExtension)
@@ -3,20 +3,26 @@
3
3
  require "csv"
4
4
 
5
5
  include YARD::Markdown::ObjectListingHelper,
6
- YARD::Markdown::ArefHelper,
7
6
  YARD::Templates::Helpers::ModuleHelper
8
7
 
9
8
  # Prepares the markdown serializer and renders each object page.
10
9
  #
11
10
  # @return [void]
12
11
  def init
13
- options.objects = objects = run_verifier(options.objects).reject { |item| item.name == :root }
12
+ objects = run_verifier(options.objects).reject { |item| item.name == :root }
13
+ files = Array(options.files).select { |file| file.filename.match?(YARD::Markdown::FILE_PATTERN) }
14
+ options.copied_file_aliases = files.to_h do |file|
15
+ path = Pathname.new(file.filename).cleanpath.to_s
16
+ [path.sub(YARD::Markdown::FILE_PATTERN, ""), path]
17
+ end
14
18
 
15
19
  options.delete(:objects)
16
20
  options.delete(:files)
17
21
 
18
22
  options.serializer.extension = "md"
19
23
 
24
+ files.each { |file| options.serializer.serialize(file.filename, File.binread(file.filename)) }
25
+
20
26
  objects.each do |object|
21
27
  Templates::Engine.with_serializer(object, options.serializer) { serialize(object) }
22
28
  rescue => e
@@ -25,7 +31,7 @@ def init
25
31
  log.backtrace(e)
26
32
  end
27
33
 
28
- serialize_index(objects)
34
+ serialize_index(objects, files)
29
35
  end
30
36
 
31
37
  # Renders the markdown template for a single namespace object.
@@ -39,16 +45,17 @@ end
39
45
  # Writes the CSV search index for all rendered objects.
40
46
  #
41
47
  # @param objects [Array<YARD::CodeObjects::NamespaceObject>] Verified objects included in the generated documentation.
48
+ # @param files [Array<YARD::CodeObjects::ExtraFileObject>] Markdown files included in the generated documentation.
42
49
  # @return [void]
43
- def serialize_index(objects)
50
+ def serialize_index(objects, files)
44
51
  filepath = "#{options.serializer.basepath}/index.csv"
45
52
 
46
53
  CSV.open(filepath, "wb") do |csv|
47
54
  csv << %w[name type path]
48
55
 
49
- objects.each do |object|
50
- next if object.name == :root
56
+ files.each { |file| csv << [file.filename, "File", file.filename] }
51
57
 
58
+ objects.each do |object|
52
59
  if object.type == :class
53
60
  csv << [object.path, "Class", options.serializer.serialized_path(object)]
54
61
  elsif object.type == :module
@@ -56,7 +63,7 @@ def serialize_index(objects)
56
63
  end
57
64
 
58
65
  [
59
- ["Constant", constant_listing(object)],
66
+ ["Constant", YARD::Markdown::ObjectListingHelper.constant_listing(object)],
60
67
  ["Method", public_instance_methods(object)],
61
68
  ["Method", public_class_methods(object)],
62
69
  ["Attribute", attr_listing(object)]
@@ -65,7 +72,7 @@ def serialize_index(objects)
65
72
  csv << [
66
73
  "#{object.path}.#{item.name(false)}",
67
74
  type,
68
- options.serializer.serialized_path(object) + "#" + aref(item)
75
+ options.serializer.serialized_path(object) + "#" + YARD::Markdown::ArefHelper.aref(item)
69
76
  ]
70
77
  end
71
78
  end
@@ -1,10 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- include YARD::Markdown::TagFormattingHelper,
4
- YARD::Markdown::SectionAssemblyHelper,
5
- YARD::Markdown::MetadataSectionHelper,
3
+ include YARD::Markdown::MetadataSectionHelper,
6
4
  YARD::Markdown::ObjectListingHelper,
7
- YARD::Markdown::MethodPresentationHelper,
8
5
  YARD::Markdown::LinkNormalizationHelper,
9
6
  YARD::Markdown::HeadingHelper,
10
7
  YARD::Markdown::DocumentationHelper,
@@ -45,48 +42,49 @@ end
45
42
  #
46
43
  # @return [String] Markdown heading section.
47
44
  def header
48
- render_section_content(heading_with_anchors("# #{object.type.to_s.capitalize} #{object.path}", object))
45
+ YARD::Markdown::SectionAssemblyHelper.render_section_content(heading_with_anchors("# #{object.type.to_s.capitalize} #{object.path}", object))
49
46
  end
50
47
 
51
48
  # Renders metadata for the current object.
52
49
  #
53
50
  # @return [String] Markdown metadata section.
54
51
  def metadata
55
- render_section_content(object_metadata(object))
52
+ YARD::Markdown::SectionAssemblyHelper.render_section_content(object_metadata(object))
56
53
  end
57
54
 
58
55
  # Renders the object's docstring as markdown.
59
56
  #
60
57
  # @return [String] Markdown docstring section.
61
58
  def docstring_section
62
- render_section_content(rdoc_to_md(object.docstring))
59
+ YARD::Markdown::SectionAssemblyHelper.render_section_content(rdoc_to_md(object.docstring))
63
60
  end
64
61
 
65
62
  # Renders the object's YARD tags.
66
63
  #
67
64
  # @return [String] Markdown tags section.
68
65
  def tags_section
69
- render_section_content(render_tags(object))
66
+ YARD::Markdown::SectionAssemblyHelper.render_section_content(YARD::Markdown::TagFormattingHelper.render_tags(object))
70
67
  end
71
68
 
72
69
  # Renders the constants section when visible constants are present.
73
70
  #
74
71
  # @return [String] Markdown constants section, or an empty string.
75
72
  def constants_section
76
- constants = constant_listing(object).reject { |item| hidden_object?(item) }
73
+ constants = YARD::Markdown::ObjectListingHelper.constant_listing(object)
74
+ .reject { |item| YARD::Markdown::ObjectListingHelper.hidden_object?(item) }
77
75
  return "" unless constants.any?
78
76
 
79
- render_section_content(render_constants(constants, Array(object.groups)))
77
+ YARD::Markdown::SectionAssemblyHelper.render_section_content(render_constants(constants, Array(object.groups)))
80
78
  end
81
79
 
82
80
  # Renders the attributes section when visible attributes are present.
83
81
  #
84
82
  # @return [String] Markdown attributes section, or an empty string.
85
83
  def attributes_section
86
- attrs = attr_listing(object).reject { |item| hidden_object?(item) }
84
+ attrs = attr_listing(object).reject { |item| YARD::Markdown::ObjectListingHelper.hidden_object?(item) }
87
85
  return "" unless attrs.any?
88
86
 
89
- render_section_content(render_attributes(attrs, Array(object.groups)))
87
+ YARD::Markdown::SectionAssemblyHelper.render_section_content(render_attributes(attrs, Array(object.groups)))
90
88
  end
91
89
 
92
90
  # Renders the public class methods section when methods are present.
@@ -96,7 +94,7 @@ def public_class_methods_section
96
94
  methods = public_class_methods(object)
97
95
  return "" unless methods.any?
98
96
 
99
- render_section_content(render_methods("Public Class Methods", methods, Array(object.groups)))
97
+ YARD::Markdown::SectionAssemblyHelper.render_section_content(render_methods("Public Class Methods", methods, Array(object.groups)))
100
98
  end
101
99
 
102
100
  # Renders the public instance methods section when methods are present.
@@ -106,5 +104,5 @@ def public_instance_methods_section
106
104
  methods = public_instance_methods(object)
107
105
  return "" unless methods.any?
108
106
 
109
- render_section_content(render_methods("Public Instance Methods", methods, Array(object.groups)))
107
+ YARD::Markdown::SectionAssemblyHelper.render_section_content(render_methods("Public Instance Methods", methods, Array(object.groups)))
110
108
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yard-markdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stanislav (Stas) Katkov
@@ -62,6 +62,7 @@ files:
62
62
  - LICENSE.txt
63
63
  - README.md
64
64
  - lib/yard-markdown.rb
65
+ - lib/yard/markdown.rb
65
66
  - lib/yard/markdown/aref_helper.rb
66
67
  - lib/yard/markdown/collection_rendering_helper.rb
67
68
  - lib/yard/markdown/documentation_helper.rb
@@ -72,6 +73,7 @@ files:
72
73
  - lib/yard/markdown/object_listing_helper.rb
73
74
  - lib/yard/markdown/section_assembly_helper.rb
74
75
  - lib/yard/markdown/tag_formatting_helper.rb
76
+ - lib/yard/markdown/yardoc_extension.rb
75
77
  - templates/default/fulldoc/markdown/setup.rb
76
78
  - templates/default/module/markdown/setup.rb
77
79
  homepage: https://poshtui.com