rdoc-markdown 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/lib/rdoc/generator/markdown.rb +52 -143
- data/lib/rdoc/markdown/version.rb +1 -1
- data/lib/templates/classfile.md.erb +1 -1
- 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: 6c8f2f083fa79cfc383a5de5efe80ed2ce86ca5c8820218ae57f9de9427f8e6e
|
|
4
|
+
data.tar.gz: b9380e6323ce669abc903f3fb29f598cd346f017c565ef4c7f8d48146124184a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7245acbe5230c82d9209a9203d9c86dfcd18416b1a60b56c574b5c59bbf81a752c388771e81e7cb135d9197620f2bc7f497db3ad33a0d7151ae1032b1f0b8115
|
|
7
|
+
data.tar.gz: 547ef3178aceffcf1e44ace777f18e97ed4ffc370ab3e99526ebbcebc053eca307c0c57e9f5d739ebc3b8156912c1b9dc13fbb08289408130c1bc38c92d87855
|
data/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
|
|
4
4
|
## Unreleased
|
|
5
5
|
|
|
6
|
+
## 0.17.0
|
|
7
|
+
|
|
8
|
+
- Remove fabricated external namespaces and preserve exact class and module identities across generated paths, index entries, metadata, and links.
|
|
9
|
+
- Avoid broken alias links when the target method is hidden or its owner page is not generated.
|
|
10
|
+
- Preserve localized section bodies, Markdown format, and source location when translating comments.
|
|
11
|
+
- Avoid duplicate unresolved cross-reference warnings during class and module selection.
|
|
12
|
+
|
|
13
|
+
## 0.16.1
|
|
14
|
+
|
|
15
|
+
- Fix copying Markdown pages when RDoc receives relative input paths.
|
|
16
|
+
|
|
6
17
|
## 0.16.0
|
|
7
18
|
|
|
8
19
|
- Don't convert markdown files from source folder. Just copy them.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -123,7 +123,7 @@ rake vendor:setup:rails
|
|
|
123
123
|
bundle exec rake test
|
|
124
124
|
```
|
|
125
125
|
|
|
126
|
-
The rails harness validates alias rendering, preserved code blocks, file/page links rewritten to markdown, and
|
|
126
|
+
The rails harness validates alias rendering, preserved code blocks, file/page links rewritten to markdown, and omission of fabricated external namespaces.
|
|
127
127
|
|
|
128
128
|
### Generate vendored docs
|
|
129
129
|
Use rake tasks to generate markdown output for vendored projects:
|
|
@@ -98,6 +98,7 @@ class RDoc::Generator::Markdown
|
|
|
98
98
|
def initialize(store, rdoc_options)
|
|
99
99
|
@store = store
|
|
100
100
|
@options = rdoc_options
|
|
101
|
+
@source_dir = File.expand_path(rdoc_options.root.to_s)
|
|
101
102
|
@markdown_unknown_tags = self.class.validate_markdown_unknown_tags(rdoc_options.markdown_unknown_tags)
|
|
102
103
|
end
|
|
103
104
|
|
|
@@ -151,14 +152,14 @@ class RDoc::Generator::Markdown
|
|
|
151
152
|
|
|
152
153
|
@classes.each do |klass|
|
|
153
154
|
csv << [
|
|
154
|
-
|
|
155
|
+
klass.full_name,
|
|
155
156
|
klass.type.capitalize,
|
|
156
157
|
output_path_for(klass)
|
|
157
158
|
]
|
|
158
159
|
|
|
159
160
|
klass.method_list.select(&:display?).each do |method|
|
|
160
161
|
csv << [
|
|
161
|
-
"#{
|
|
162
|
+
"#{klass.full_name}.#{method.name}",
|
|
162
163
|
"Method",
|
|
163
164
|
"#{output_path_for(klass)}##{method.aref}"
|
|
164
165
|
]
|
|
@@ -170,7 +171,7 @@ class RDoc::Generator::Markdown
|
|
|
170
171
|
.sort
|
|
171
172
|
.each do |const|
|
|
172
173
|
csv << [
|
|
173
|
-
"#{
|
|
174
|
+
"#{klass.full_name}.#{const.name}",
|
|
174
175
|
"Constant",
|
|
175
176
|
"#{output_path_for(klass)}##{const.name}"
|
|
176
177
|
]
|
|
@@ -182,7 +183,7 @@ class RDoc::Generator::Markdown
|
|
|
182
183
|
.sort
|
|
183
184
|
.each do |attr|
|
|
184
185
|
csv << [
|
|
185
|
-
"#{
|
|
186
|
+
"#{klass.full_name}.#{attr.name}",
|
|
186
187
|
"Attribute",
|
|
187
188
|
"#{output_path_for(klass)}##{attr.aref}"
|
|
188
189
|
]
|
|
@@ -223,7 +224,7 @@ class RDoc::Generator::Markdown
|
|
|
223
224
|
out_file = Pathname.new("#{output_dir}/#{page_output_path(page)}")
|
|
224
225
|
out_file.dirname.mkpath
|
|
225
226
|
|
|
226
|
-
next FileUtils.cp(page.absolute_name, out_file) if page.relative_name.end_with?(".md", ".markdown")
|
|
227
|
+
next FileUtils.cp(File.expand_path(page.absolute_name, @source_dir), out_file) if page.relative_name.end_with?(".md", ".markdown")
|
|
227
228
|
|
|
228
229
|
content = markdownify(render_description(page))
|
|
229
230
|
File.write(out_file, finalize_markdown(
|
|
@@ -259,22 +260,13 @@ class RDoc::Generator::Markdown
|
|
|
259
260
|
"#{dirname}/#{basename}"
|
|
260
261
|
end
|
|
261
262
|
|
|
262
|
-
# Returns the normalized display name for a class or module.
|
|
263
|
-
#
|
|
264
|
-
# @param code_object [RDoc::Context] Class or module object.
|
|
265
|
-
#
|
|
266
|
-
# @return [String] Display name used in headings and the index.
|
|
267
|
-
def display_name(code_object)
|
|
268
|
-
class_doc_for(code_object).fetch(:display_name)
|
|
269
|
-
end
|
|
270
|
-
|
|
271
263
|
# Returns the canonical Markdown path for a class or module.
|
|
272
264
|
#
|
|
273
265
|
# @param code_object [RDoc::Context] Class or module object.
|
|
274
266
|
#
|
|
275
267
|
# @return [String] Relative Markdown path.
|
|
276
268
|
def output_path_for(code_object)
|
|
277
|
-
|
|
269
|
+
turn_to_path(code_object.full_name)
|
|
278
270
|
end
|
|
279
271
|
|
|
280
272
|
# Renders a class or module reference, linking it when its documentation is emitted.
|
|
@@ -284,11 +276,11 @@ class RDoc::Generator::Markdown
|
|
|
284
276
|
#
|
|
285
277
|
# @return [String] Markdown text or link.
|
|
286
278
|
def metadata_reference(target, label)
|
|
287
|
-
|
|
279
|
+
output_path = @class_output_paths[target.full_name] if target.respond_to?(:full_name)
|
|
288
280
|
cell = metadata_table_cell(label)
|
|
289
|
-
return cell unless
|
|
281
|
+
return cell unless output_path
|
|
290
282
|
|
|
291
|
-
"[#{cell}](#{
|
|
283
|
+
"[#{cell}](#{output_path})"
|
|
292
284
|
end
|
|
293
285
|
|
|
294
286
|
# Escapes text for a Markdown table cell.
|
|
@@ -389,16 +381,31 @@ class RDoc::Generator::Markdown
|
|
|
389
381
|
#
|
|
390
382
|
# @param code_object [RDoc::CodeObject, RDoc::Context::Section] Object whose description is rendered.
|
|
391
383
|
#
|
|
392
|
-
# @return [String
|
|
384
|
+
# @return [String] HTML description.
|
|
393
385
|
def render_description(code_object)
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
386
|
+
section = RDoc::Context::Section === code_object
|
|
387
|
+
formatter = if section
|
|
388
|
+
code_object.parent.formatter.dup.tap { |copy| copy.code_object = code_object }
|
|
389
|
+
else
|
|
390
|
+
code_object.formatter
|
|
391
|
+
end
|
|
397
392
|
formatter.extend(CrossrefExtension)
|
|
398
393
|
begin
|
|
399
394
|
formatter.markdown_cross_reference = RDoc::CrossReference.new(formatter.context)
|
|
400
395
|
formatter.markdown_output_object_ids = @markdown_output_object_ids
|
|
401
|
-
|
|
396
|
+
if section
|
|
397
|
+
locale = options.locale
|
|
398
|
+
documents = code_object.comments.map do |comment|
|
|
399
|
+
next comment.parse unless locale && !comment.text.empty?
|
|
400
|
+
|
|
401
|
+
comment = comment.dup
|
|
402
|
+
comment.text = RDoc::I18n::Text.new(comment).translate(locale)
|
|
403
|
+
comment.parse
|
|
404
|
+
end
|
|
405
|
+
RDoc::Markup::Document.new(*documents).accept(formatter)
|
|
406
|
+
else
|
|
407
|
+
code_object.description
|
|
408
|
+
end
|
|
402
409
|
ensure
|
|
403
410
|
formatter.markdown_cross_reference = nil
|
|
404
411
|
end
|
|
@@ -584,7 +591,10 @@ class RDoc::Generator::Markdown
|
|
|
584
591
|
aliased_method = method.is_alias_for
|
|
585
592
|
return "Not documented." unless aliased_method
|
|
586
593
|
|
|
587
|
-
|
|
594
|
+
link = method_link(aliased_method, current_class: current_class)
|
|
595
|
+
return "Alias for: `#{aliased_method.name}`" unless link
|
|
596
|
+
|
|
597
|
+
"Alias for: [`#{aliased_method.name}`](#{link})"
|
|
588
598
|
end
|
|
589
599
|
|
|
590
600
|
# Applies final whitespace and link normalization before writing Markdown.
|
|
@@ -661,12 +671,16 @@ class RDoc::Generator::Markdown
|
|
|
661
671
|
# @param method [RDoc::AnyMethod] Target method.
|
|
662
672
|
# @param current_class [RDoc::Context] Class or module currently being rendered.
|
|
663
673
|
#
|
|
664
|
-
# @return [String] Anchor or relative Markdown link target.
|
|
674
|
+
# @return [String, nil] Anchor or relative Markdown link target, or nil when the target page is omitted.
|
|
665
675
|
def method_link(method, current_class:)
|
|
676
|
+
return unless method.display?
|
|
677
|
+
|
|
666
678
|
target_parent = method.parent
|
|
679
|
+
target_path = @class_output_paths[target_parent.full_name]
|
|
680
|
+
return unless target_path
|
|
667
681
|
return "##{method.aref}" if target_parent == current_class
|
|
668
682
|
|
|
669
|
-
"#{
|
|
683
|
+
"#{target_path}##{method.aref}"
|
|
670
684
|
end
|
|
671
685
|
|
|
672
686
|
# Rewrites local Markdown links relative to the current output file.
|
|
@@ -719,7 +733,7 @@ class RDoc::Generator::Markdown
|
|
|
719
733
|
def normalize_input_path_for_output(path)
|
|
720
734
|
normalized = path.tr("\\", "/").sub(%r{\A\./}, "")
|
|
721
735
|
|
|
722
|
-
root =
|
|
736
|
+
root = @source_dir
|
|
723
737
|
normalized = normalized.sub(%r{\A#{Regexp.escape(root)}/}, "")
|
|
724
738
|
normalized = normalized.sub(%r{\A/}, "")
|
|
725
739
|
|
|
@@ -727,117 +741,6 @@ class RDoc::Generator::Markdown
|
|
|
727
741
|
normalized.sub(%r{\A#{Regexp.escape(root_basename)}/}, "")
|
|
728
742
|
end
|
|
729
743
|
|
|
730
|
-
# Looks up resolved class documentation metadata.
|
|
731
|
-
#
|
|
732
|
-
# @param code_object [RDoc::Context] Class or module object.
|
|
733
|
-
#
|
|
734
|
-
# @return [Hash{Symbol => Object}] Metadata for rendering the object.
|
|
735
|
-
def class_doc_for(code_object)
|
|
736
|
-
@class_docs_by_object_id.fetch(code_object.object_id)
|
|
737
|
-
end
|
|
738
|
-
|
|
739
|
-
# Builds canonical class documentation metadata from RDoc objects.
|
|
740
|
-
#
|
|
741
|
-
# @param classes [Array<RDoc::Context>] Classes and modules to normalize.
|
|
742
|
-
#
|
|
743
|
-
# @return [Array<Hash{Symbol => Object}>] Metadata ordered by display name.
|
|
744
|
-
def build_class_docs(classes)
|
|
745
|
-
docs_by_name = {}
|
|
746
|
-
|
|
747
|
-
classes.select(&:display?).each do |klass|
|
|
748
|
-
display_name = normalized_full_name(klass.full_name)
|
|
749
|
-
output_path = turn_to_path(display_name)
|
|
750
|
-
score = class_content_score(klass)
|
|
751
|
-
|
|
752
|
-
candidate = {
|
|
753
|
-
klass: klass,
|
|
754
|
-
display_name: display_name,
|
|
755
|
-
output_path: output_path,
|
|
756
|
-
score: score
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
existing = docs_by_name[display_name]
|
|
760
|
-
|
|
761
|
-
if existing.nil?
|
|
762
|
-
docs_by_name[display_name] = candidate
|
|
763
|
-
elsif candidate.fetch(:score) > existing.fetch(:score)
|
|
764
|
-
docs_by_name[display_name] = candidate
|
|
765
|
-
end
|
|
766
|
-
end
|
|
767
|
-
|
|
768
|
-
docs_by_name.values
|
|
769
|
-
.select do |doc|
|
|
770
|
-
klass = doc.fetch(:klass)
|
|
771
|
-
|
|
772
|
-
doc.fetch(:score).positive? ||
|
|
773
|
-
(!class_has_raw_members?(klass) && !synthetic_full_name?(klass.full_name))
|
|
774
|
-
end
|
|
775
|
-
.sort_by { |doc| doc.fetch(:display_name) }
|
|
776
|
-
end
|
|
777
|
-
|
|
778
|
-
# Collapses repeated namespace segments from synthetic vendored names.
|
|
779
|
-
#
|
|
780
|
-
# @param full_name [String] Full RDoc object name.
|
|
781
|
-
#
|
|
782
|
-
# @return [String] Normalized object name.
|
|
783
|
-
def normalized_full_name(full_name)
|
|
784
|
-
normalized = full_name
|
|
785
|
-
|
|
786
|
-
loop do
|
|
787
|
-
if normalized =~ /\A([^:]+)(?:::[^:]+)+::\1::(.+)\z/
|
|
788
|
-
normalized = "#{Regexp.last_match(1)}::#{Regexp.last_match(2)}"
|
|
789
|
-
end
|
|
790
|
-
|
|
791
|
-
if normalized =~ /\A(.+?)::\1\z/
|
|
792
|
-
normalized = Regexp.last_match(1)
|
|
793
|
-
end
|
|
794
|
-
|
|
795
|
-
break
|
|
796
|
-
end
|
|
797
|
-
|
|
798
|
-
normalized
|
|
799
|
-
end
|
|
800
|
-
|
|
801
|
-
# Scores how much owned content a class or module has.
|
|
802
|
-
#
|
|
803
|
-
# @param klass [RDoc::Context] Class or module object.
|
|
804
|
-
#
|
|
805
|
-
# @return [Integer] Content score used to choose duplicate docs.
|
|
806
|
-
def class_content_score(klass)
|
|
807
|
-
score = class_member_count(klass)
|
|
808
|
-
score += 1 unless klass.description.empty?
|
|
809
|
-
score
|
|
810
|
-
end
|
|
811
|
-
|
|
812
|
-
# Counts methods, constants, and attributes owned by a class or module.
|
|
813
|
-
#
|
|
814
|
-
# @param klass [RDoc::Context] Class or module object.
|
|
815
|
-
#
|
|
816
|
-
# @return [Integer] Number of owned members.
|
|
817
|
-
def class_member_count(klass)
|
|
818
|
-
klass.method_list.count(&:display?) + klass.constants.count(&:display?) + klass.attributes.count(&:display?)
|
|
819
|
-
end
|
|
820
|
-
|
|
821
|
-
# Checks whether a class or module owns any members before display filtering.
|
|
822
|
-
#
|
|
823
|
-
# @param klass [RDoc::Context] Class or module object.
|
|
824
|
-
#
|
|
825
|
-
# @return [Boolean] True when any owned member exists before display filtering.
|
|
826
|
-
def class_has_raw_members?(klass)
|
|
827
|
-
klass.method_list.any? || klass.constants.any? || klass.attributes.any?
|
|
828
|
-
end
|
|
829
|
-
|
|
830
|
-
# Checks whether a name appears to contain duplicated root namespaces.
|
|
831
|
-
#
|
|
832
|
-
# @param full_name [String] Full RDoc object name.
|
|
833
|
-
#
|
|
834
|
-
# @return [Boolean] True when the root namespace appears more than once.
|
|
835
|
-
def synthetic_full_name?(full_name)
|
|
836
|
-
parts = full_name.split("::")
|
|
837
|
-
root = parts.first
|
|
838
|
-
parts.count(root) > 1
|
|
839
|
-
end
|
|
840
|
-
|
|
841
744
|
# Prepares sorted objects and link lookup state for generation.
|
|
842
745
|
#
|
|
843
746
|
# @return [void]
|
|
@@ -847,13 +750,19 @@ class RDoc::Generator::Markdown
|
|
|
847
750
|
raise TypeError, "RDoc markdown output directory must be a String"
|
|
848
751
|
end
|
|
849
752
|
|
|
850
|
-
@
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
753
|
+
@classes = @store.unique_classes_and_modules.select(&:display?).select do |klass|
|
|
754
|
+
klass.in_files.any? ||
|
|
755
|
+
klass.documented? ||
|
|
756
|
+
klass.includes.any? ||
|
|
757
|
+
klass.method_list.any?(&:display?) ||
|
|
758
|
+
klass.constants.any?(&:display?) ||
|
|
759
|
+
klass.attributes.any?(&:display?) ||
|
|
760
|
+
klass.sections.any? { |section| section.title.to_s.match?(/\S/) || !section.to_document.empty? }
|
|
761
|
+
end.sort
|
|
762
|
+
@class_output_paths = @classes.to_h { |klass| [klass.full_name, output_path_for(klass)] }
|
|
854
763
|
@pages = @store.all_files.select(&:text?).select(&:display?).sort_by(&:base_name)
|
|
855
764
|
@markdown_output_object_ids = (@classes + @pages).map(&:object_id)
|
|
856
|
-
@known_output_paths = @
|
|
765
|
+
@known_output_paths = @class_output_paths.values
|
|
857
766
|
@pages.each { |page| @known_output_paths << page_output_path(page) }
|
|
858
767
|
|
|
859
768
|
@root_path_segment = Pathname.new(@options.root || ".").basename
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# <%= klass.type.capitalize %> <%=
|
|
1
|
+
# <%= klass.type.capitalize %> <%= klass.full_name %><%= anchor(klass.aref.strip) %>
|
|
2
2
|
<%- superclass = klass.superclass if klass.type == "class" -%>
|
|
3
3
|
<%- includes = klass.includes -%>
|
|
4
4
|
<%- source_files = klass.in_files -%>
|