yard-markdown 0.9.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 +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +0 -4
- data/lib/yard/markdown/aref_helper.rb +32 -13
- data/lib/yard/markdown/collection_rendering_helper.rb +29 -18
- data/lib/yard/markdown/documentation_helper.rb +27 -10
- data/lib/yard/markdown/heading_helper.rb +12 -13
- data/lib/yard/markdown/link_normalization_helper.rb +102 -57
- data/lib/yard/markdown/metadata_section_helper.rb +43 -18
- data/lib/yard/markdown/method_presentation_helper.rb +5 -7
- data/lib/yard/markdown/object_listing_helper.rb +35 -29
- data/lib/yard/markdown/section_assembly_helper.rb +10 -17
- data/lib/yard/markdown/tag_formatting_helper.rb +17 -29
- data/lib/yard/markdown/yardoc_extension.rb +38 -11
- data/templates/default/fulldoc/markdown/setup.rb +4 -7
- data/templates/default/module/markdown/setup.rb +12 -14
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 80c8051a8c7527055a46d9dcad2db56a019f54bb99315e25813a010152fd2df3
|
|
4
|
+
data.tar.gz: 7187cf79b4ea2ef53b859cb17971681eefc3981e2d3da9718dead415a2b503f2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 71b9f9638c8f7da302a2d8a412524bef3bb77aa7a0ec5f38a8cdc45fa04f4a65e34b0d6e7bb9c0b42e765c474041ec6b9a2845d7136f11552dd64e6f4fc52720
|
|
7
|
+
data.tar.gz: 6e1459ddb1e780dc708d67a1bc13d8f7315bfd8041a07c72207bf66af6bf4d9b91ce9833d7346ec78eef2708eff449932bb6d2743d4e64b8ea5bfe87d3d71e4a
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,10 @@ 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
|
+
|
|
8
12
|
## 0.9.0
|
|
9
13
|
|
|
10
14
|
- Detect Markdown files, copy them into generated documentation, and include them in `index.csv`.
|
data/README.md
CHANGED
|
@@ -21,10 +21,6 @@ Run `yardoc --format=markdown` to generate markdown documentation.
|
|
|
21
21
|
|
|
22
22
|
Markdown files in the project tree are detected automatically, copied unchanged into the output, and listed in `index.csv`:
|
|
23
23
|
|
|
24
|
-
```bash
|
|
25
|
-
yardoc --format=markdown
|
|
26
|
-
```
|
|
27
|
-
|
|
28
24
|
Markdown files whose basename starts with `_` are ignored automatically.
|
|
29
25
|
|
|
30
26
|
Use YARD's `--exclude` option to omit a separate documentation tree:
|
|
@@ -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
|
|
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
|
-
|
|
34
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
48
|
-
|
|
52
|
+
["## #{section_title}", body].join("\n")
|
|
53
|
+
end
|
|
49
54
|
|
|
50
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
35
|
-
|
|
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
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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,11 +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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
output = output.gsub(/\n{3,}/, "\n\n").strip
|
|
17
|
-
"#{output}\n"
|
|
13
|
+
LinkNormalizationHelper.finish_markdown(
|
|
14
|
+
normalize_local_links(LinkNormalizationHelper.normalize_lines(content), current_path)
|
|
15
|
+
)
|
|
18
16
|
end
|
|
19
17
|
|
|
20
18
|
# Rewrites local Markdown links relative to the current output path.
|
|
@@ -26,17 +24,7 @@ module YARD
|
|
|
26
24
|
current_dir = Pathname.new(current_path).dirname
|
|
27
25
|
|
|
28
26
|
markdown.gsub(%r{\[(.+?)\]\((?!https?://|mailto:|#)([^)\n]+)\)}) do
|
|
29
|
-
|
|
30
|
-
target = Regexp.last_match(2)
|
|
31
|
-
path = target.sub(/[?#].*\z/, "")
|
|
32
|
-
suffix = target[path.length..]
|
|
33
|
-
rewritten_path = resolve_local_link_target(path, current_dir)
|
|
34
|
-
|
|
35
|
-
if rewritten_path.nil?
|
|
36
|
-
"`#{label.tr("`", "")}`"
|
|
37
|
-
else
|
|
38
|
-
"[#{label}](#{rewritten_path}#{suffix})"
|
|
39
|
-
end
|
|
27
|
+
normalize_local_link(Regexp.last_match, current_dir)
|
|
40
28
|
end
|
|
41
29
|
end
|
|
42
30
|
|
|
@@ -45,28 +33,37 @@ module YARD
|
|
|
45
33
|
# @param path [String] Link target path to resolve.
|
|
46
34
|
# @param current_dir [Pathname] Directory for the current output file.
|
|
47
35
|
# @return [YARD::CodeObjects::Base, nil] Matched registry object, if any.
|
|
48
|
-
def resolve_registry_object(path, current_dir)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
current_parts.length.downto(0) do |depth|
|
|
57
|
-
candidates << (current_parts.first(depth) + target_parts).join("::")
|
|
58
|
-
end
|
|
59
|
-
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
|
|
60
43
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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)
|
|
64
52
|
|
|
65
|
-
|
|
66
|
-
|
|
53
|
+
namespaced_candidates(cleaned, current_dir)
|
|
54
|
+
end
|
|
67
55
|
|
|
68
|
-
|
|
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("::") }
|
|
69
65
|
end
|
|
66
|
+
private_class_method :registry_candidates, :namespaced_candidates
|
|
70
67
|
|
|
71
68
|
# Resolves a local link target to the final relative Markdown path.
|
|
72
69
|
#
|
|
@@ -75,33 +72,15 @@ module YARD
|
|
|
75
72
|
# @return [String, nil] Relative Markdown path, or nil when unresolved.
|
|
76
73
|
def resolve_local_link_target(path, current_dir)
|
|
77
74
|
normalized = path.sub(%r{\A/+}, "")
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if obj
|
|
81
|
-
object_path = options.serializer.serialized_path(obj)
|
|
82
|
-
return relative_output_path(current_dir, object_path)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
alias_path = Pathname.new(normalized.sub(/\.html\z/i, "")).cleanpath.to_s
|
|
86
|
-
copied_path = options.copied_file_aliases[alias_path]
|
|
87
|
-
return relative_output_path(current_dir, copied_path) if copied_path
|
|
88
|
-
|
|
89
|
-
if normalized.match?(/\.html\z/i)
|
|
90
|
-
normalized = normalized.sub(/\.html\z/i, ".md")
|
|
91
|
-
elsif File.extname(normalized).empty?
|
|
92
|
-
return nil if unresolved_identifier_target?(normalized)
|
|
93
|
-
|
|
94
|
-
normalized = "#{normalized}.md"
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
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
|
|
98
77
|
end
|
|
99
78
|
|
|
100
79
|
# Returns whether a path looks like a constant reference.
|
|
101
80
|
#
|
|
102
81
|
# @param value [String] Link target to inspect.
|
|
103
82
|
# @return [Boolean] True when the path resembles a constant name.
|
|
104
|
-
def constant_reference_path?(value)
|
|
83
|
+
def self.constant_reference_path?(value)
|
|
105
84
|
parts = value.split(%r{::|/}).reject(&:empty?)
|
|
106
85
|
return false if parts.empty?
|
|
107
86
|
|
|
@@ -112,7 +91,7 @@ module YARD
|
|
|
112
91
|
#
|
|
113
92
|
# @param path [String] Link target to inspect.
|
|
114
93
|
# @return [Boolean] True when the target should be treated as unresolved.
|
|
115
|
-
def unresolved_identifier_target?(path)
|
|
94
|
+
def self.unresolved_identifier_target?(path)
|
|
116
95
|
cleaned = path.sub(%r{\A(?:(?:\.\./)+|\./)}, "")
|
|
117
96
|
File.extname(cleaned).empty? && !cleaned.include?("/")
|
|
118
97
|
end
|
|
@@ -122,7 +101,7 @@ module YARD
|
|
|
122
101
|
# @param current_dir [Pathname] Directory for the current output file.
|
|
123
102
|
# @param target_path [String, Pathname] Output path being linked to.
|
|
124
103
|
# @return [String] Relative path suitable for a Markdown link.
|
|
125
|
-
def relative_output_path(current_dir, target_path)
|
|
104
|
+
def self.relative_output_path(current_dir, target_path)
|
|
126
105
|
target = target_path.to_s
|
|
127
106
|
return target if target.start_with?("../")
|
|
128
107
|
|
|
@@ -130,6 +109,72 @@ module YARD
|
|
|
130
109
|
rescue
|
|
131
110
|
target
|
|
132
111
|
end
|
|
112
|
+
|
|
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.
|
|
171
|
+
#
|
|
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]
|
|
177
|
+
end
|
|
133
178
|
end
|
|
134
179
|
end
|
|
135
180
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
26
|
+
path = target.path
|
|
27
|
+
label = MetadataSectionHelper.metadata_table_cell(path)
|
|
39
28
|
return label unless target.is_a?(CodeObjects::NamespaceObject) && run_verifier([target]).any?
|
|
40
29
|
|
|
41
|
-
"[#{label}](#{
|
|
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
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
|
52
|
+
# Sorts attributes by scope and case-insensitive name.
|
|
66
53
|
#
|
|
67
|
-
# @param
|
|
68
|
-
# @return [Array<YARD::CodeObjects::
|
|
69
|
-
def
|
|
70
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
28
|
+
# Orders known group names by configured, alphabetical, and default order.
|
|
33
29
|
#
|
|
34
|
-
# @param
|
|
35
|
-
# @param
|
|
36
|
-
# @
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
title
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
|
@@ -11,20 +11,47 @@ module YARD
|
|
|
11
11
|
# @param checksums [Hash, nil] Previously generated file checksums.
|
|
12
12
|
# @return [void]
|
|
13
13
|
def run_generate(checksums)
|
|
14
|
-
if options.format == :markdown
|
|
15
|
-
existing = options.files.map { |file| File.expand_path(file.filename) }
|
|
16
|
-
exclusions = excluded.map { |path| Regexp.new(path, Regexp::IGNORECASE) }
|
|
17
|
-
output = File.expand_path(options.serializer.basepath)
|
|
18
|
-
markdown_files = Dir.glob("**/*").grep(FILE_PATTERN)
|
|
19
|
-
.reject { |file| File.basename(file).start_with?("_") }
|
|
20
|
-
.reject { |file| exclusions.any? { |pattern| pattern.match?(file) } }
|
|
21
|
-
.reject { |file| File.expand_path(file).start_with?("#{output}/") }
|
|
22
|
-
.reject { |file| existing.include?(File.expand_path(file)) }
|
|
23
|
-
add_extra_files(markdown_files)
|
|
24
|
-
end
|
|
14
|
+
add_extra_files(markdown_files) if options.format == :markdown
|
|
25
15
|
|
|
26
16
|
super
|
|
27
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
|
|
28
55
|
end
|
|
29
56
|
end
|
|
30
57
|
end
|
|
@@ -3,14 +3,13 @@
|
|
|
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
|
-
|
|
12
|
+
objects = run_verifier(options.objects).reject { |item| item.name == :root }
|
|
14
13
|
files = Array(options.files).select { |file| file.filename.match?(YARD::Markdown::FILE_PATTERN) }
|
|
15
14
|
options.copied_file_aliases = files.to_h do |file|
|
|
16
15
|
path = Pathname.new(file.filename).cleanpath.to_s
|
|
@@ -54,11 +53,9 @@ def serialize_index(objects, files)
|
|
|
54
53
|
CSV.open(filepath, "wb") do |csv|
|
|
55
54
|
csv << %w[name type path]
|
|
56
55
|
|
|
57
|
-
files.each { |file| csv << [file.
|
|
56
|
+
files.each { |file| csv << [file.filename, "File", file.filename] }
|
|
58
57
|
|
|
59
58
|
objects.each do |object|
|
|
60
|
-
next if object.name == :root
|
|
61
|
-
|
|
62
59
|
if object.type == :class
|
|
63
60
|
csv << [object.path, "Class", options.serializer.serialized_path(object)]
|
|
64
61
|
elsif object.type == :module
|
|
@@ -66,7 +63,7 @@ def serialize_index(objects, files)
|
|
|
66
63
|
end
|
|
67
64
|
|
|
68
65
|
[
|
|
69
|
-
["Constant", constant_listing(object)],
|
|
66
|
+
["Constant", YARD::Markdown::ObjectListingHelper.constant_listing(object)],
|
|
70
67
|
["Method", public_instance_methods(object)],
|
|
71
68
|
["Method", public_class_methods(object)],
|
|
72
69
|
["Attribute", attr_listing(object)]
|
|
@@ -75,7 +72,7 @@ def serialize_index(objects, files)
|
|
|
75
72
|
csv << [
|
|
76
73
|
"#{object.path}.#{item.name(false)}",
|
|
77
74
|
type,
|
|
78
|
-
options.serializer.serialized_path(object) + "#" + aref(item)
|
|
75
|
+
options.serializer.serialized_path(object) + "#" + YARD::Markdown::ArefHelper.aref(item)
|
|
79
76
|
]
|
|
80
77
|
end
|
|
81
78
|
end
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
include YARD::Markdown::
|
|
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)
|
|
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
|