markdown_ruby_documentation 0.2.0 → 0.3.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/README.md +6 -4
- data/lib/markdown_ruby_documentation/default_erb_methods.rb +0 -4
- data/lib/markdown_ruby_documentation/generate.rb +26 -13
- data/lib/markdown_ruby_documentation/markdown_presenter.rb +42 -16
- data/lib/markdown_ruby_documentation/summary.rb +2 -2
- data/lib/markdown_ruby_documentation/template_parser.rb +105 -34
- data/lib/markdown_ruby_documentation/template_parser/parsing.rb +8 -0
- data/lib/markdown_ruby_documentation/version.rb +1 -1
- data/lib/markdown_ruby_documentation/write_markdown_to_disk.rb +3 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0195aa8a642b4e01747ef74e449c4a0e0195fcc5
|
4
|
+
data.tar.gz: c752bf835f1c6fbf3bbf5ed968cc35a3810bb930
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a736068cff89585b1efa8dbce9dc0854effea63f90a38819dbe75c406594240824162f0e297c6095054e65824caeae4abf47f19d76fecafc7b445caa9566ca92
|
7
|
+
data.tar.gz: c2ce815983eb44535d554e0599a61588a9f1d7adff1892ad52330f3256fb6eb7a28575af2a198aa625de755f34e3483df4f920dc1aa1ad4e6f32c81673d2dd5b
|
data/README.md
CHANGED
@@ -40,7 +40,7 @@ html_generator = MarkdownRubyDocumentation::HtmlGenerator.new(
|
|
40
40
|
|
41
41
|
MarkdownRubyDocumentation::Generate.run(
|
42
42
|
subjects: [RubyClassToBeInspected],
|
43
|
-
|
43
|
+
output_object: html_generator
|
44
44
|
).call
|
45
45
|
```
|
46
46
|
|
@@ -94,7 +94,8 @@ Converts case statements and if statements to bulleted markdown
|
|
94
94
|
*example ruby_to_markdown "def method_name\n'hello'\nend", readable_ruby_numbers: false**
|
95
95
|
**option 2 - Assumes methods source of current method**
|
96
96
|
* param [Hash] disable_processors (optional) See processors list.
|
97
|
-
|
97
|
+
`example ruby_to_markdown(readable_ruby_numbers: false)`
|
98
|
+
`example ruby_to_markdown(ruby_operators_to_english: { proc: ->(replacement, match) { "do some alteration" }})`
|
98
99
|
|
99
100
|
**processors**
|
100
101
|
* readable_ruby_numbers
|
@@ -103,8 +104,9 @@ Converts case statements and if statements to bulleted markdown
|
|
103
104
|
* ternary_to_if_else
|
104
105
|
* ruby_if_statement_to_md
|
105
106
|
* ruby_case_statement_to_md
|
106
|
-
* ruby_operators_to_english
|
107
|
-
* methods_as_local_links
|
107
|
+
* ruby_operators_to_english, options: proc(replacement, match)
|
108
|
+
* methods_as_local_links, options: method_to_class: { method_name => OwningConstant }
|
109
|
+
* question_mark_method_format
|
108
110
|
* remove_end_keyword
|
109
111
|
* constants_with_name_and_value
|
110
112
|
* remove_memoized_vars
|
@@ -2,24 +2,31 @@ module MarkdownRubyDocumentation
|
|
2
2
|
class Generate
|
3
3
|
# @param [Class] subjects ruby classes to generate documentation from.
|
4
4
|
# @param [Module] erb_methods must contain #link_to_markdown and contain any additional methods for comment ERB
|
5
|
-
# @param [Proc]
|
5
|
+
# @param [Proc] output_object given name: and text: for use in saving the the files.
|
6
|
+
# @param [String] load_path
|
6
7
|
def self.run(
|
7
|
-
subjects:,
|
8
|
+
subjects:,
|
9
|
+
erb_methods: DefaultErbMethods,
|
10
|
+
output_object:,
|
11
|
+
load_path:
|
8
12
|
)
|
9
|
-
|
13
|
+
self.output_object = output_object
|
14
|
+
self.load_path = load_path
|
15
|
+
erb_methods_class = Class.new
|
10
16
|
erb_methods_class.extend TemplateParser::CommentMacros
|
11
17
|
erb_methods_class.extend erb_methods
|
12
18
|
TemplateParser::CommentMacros.include erb_methods
|
13
19
|
left_padding = subjects.map(&:name).group_by(&:size).max.first
|
14
|
-
progressbar
|
15
|
-
pages
|
20
|
+
progressbar = ProgressBar.create(title: "Compiling Markdown".ljust(left_padding), total: subjects.count+ 1)
|
21
|
+
pages = subjects.map do |subject|
|
16
22
|
progressbar.title = subject.name.ljust(left_padding)
|
17
23
|
Page.new(subject: subject,
|
18
|
-
|
19
|
-
erb_methods_class: erb_methods_class
|
24
|
+
output_object: output_object,
|
25
|
+
erb_methods_class: erb_methods_class,
|
26
|
+
load_path: load_path).call.tap { progressbar.increment }
|
20
27
|
end
|
21
28
|
|
22
|
-
return_value
|
29
|
+
return_value = pages.each_with_object({}) do |page, hash|
|
23
30
|
name_parts = page.subject.name.split("::")
|
24
31
|
name = name_parts.pop
|
25
32
|
namespace = name_parts.join("::")
|
@@ -32,26 +39,32 @@ module MarkdownRubyDocumentation
|
|
32
39
|
return_value
|
33
40
|
end
|
34
41
|
|
42
|
+
class << self
|
43
|
+
attr_accessor :load_path, :output_object
|
44
|
+
end
|
45
|
+
|
35
46
|
class Page
|
36
|
-
attr_reader :subject, :
|
47
|
+
attr_reader :subject, :output_object, :erb_methods_class, :load_path
|
37
48
|
|
38
49
|
def initialize(subject:,
|
39
50
|
methods: [],
|
40
|
-
|
51
|
+
load_path:,
|
52
|
+
output_object:,
|
41
53
|
erb_methods_class:)
|
42
54
|
initialize_methods(methods, subject)
|
43
55
|
@erb_methods_class = erb_methods_class
|
44
56
|
@subject = subject
|
45
57
|
methods = methods
|
46
58
|
@methods = methods
|
47
|
-
@
|
59
|
+
@load_path = load_path
|
60
|
+
@output_object = output_object
|
48
61
|
end
|
49
62
|
|
50
63
|
def call
|
51
64
|
methods_pipes = run_pipeline(methods_pipeline)
|
52
65
|
text = run_pipeline(string_pipeline, methods_pipes)
|
53
|
-
|
54
|
-
|
66
|
+
output_object.call(name: subject.name,
|
67
|
+
text: text)
|
55
68
|
self
|
56
69
|
end
|
57
70
|
|
@@ -4,33 +4,59 @@ module MarkdownRubyDocumentation
|
|
4
4
|
attr_reader :items, :title_key, :summary
|
5
5
|
|
6
6
|
def initialize(items: nil, summary:, title_key:, skip_blanks: true)
|
7
|
-
@items
|
8
|
-
@summary
|
9
|
-
@title_key
|
10
|
-
@skip_blanks
|
7
|
+
@items = items
|
8
|
+
@summary = summary
|
9
|
+
@title_key = title_key
|
10
|
+
@skip_blanks = skip_blanks
|
11
|
+
@present_items = []
|
11
12
|
end
|
12
13
|
|
13
14
|
def call(items=nil)
|
14
15
|
@items ||= items
|
15
|
-
|
16
|
-
# #{summary.title}
|
17
|
-
|
18
|
-
|
19
|
-
#{present_items}
|
20
|
-
MD
|
16
|
+
return "" if nothing_to_display?
|
17
|
+
md = ["# #{summary.title}", "#{summary.summary}\n".gsub(/\n\n\n/, "\n\n"), instances_methods, class_methods, "#{null_methods}\n".gsub(/\n\n\n/, "\n\n")].join("\n").gsub(/[\n]+\Z/, "\n\n")
|
18
|
+
other_types!
|
19
|
+
md
|
21
20
|
end
|
22
21
|
|
23
22
|
private
|
24
23
|
|
25
|
-
def
|
26
|
-
items.
|
27
|
-
|
24
|
+
def item_types
|
25
|
+
@item_types ||= items.group_by { |_, hash| hash[:method_object].class.name }
|
26
|
+
end
|
27
|
+
|
28
|
+
def instances_methods
|
29
|
+
@instance_methods ||= item_types.delete("MarkdownRubyDocumentation::InstanceMethod") || {}
|
30
|
+
@instance_methods.map do |name, hash|
|
31
|
+
%[## #{name.to_s.titleize}\n#{hash[:text]}] unless hash[:text].blank?
|
32
|
+
end.join("\n\n")
|
33
|
+
end
|
34
|
+
|
35
|
+
def class_methods
|
36
|
+
@class_methods ||= item_types.delete("MarkdownRubyDocumentation::ClassMethod") || {}
|
37
|
+
@class_methods.map do |name, hash|
|
28
38
|
%[## #{name.to_s.titleize}\n#{hash[:text]}] unless hash[:text].blank?
|
29
|
-
rescue =>e
|
30
|
-
puts e
|
31
|
-
end
|
32
39
|
end.join("\n\n")
|
33
40
|
end
|
34
41
|
|
42
|
+
def null_methods
|
43
|
+
@null_methods ||= item_types.delete("MarkdownRubyDocumentation::NullMethod") || {}
|
44
|
+
md = @null_methods.map do |name, hash|
|
45
|
+
%[### #{name.to_s.titleize}\n#{hash[:text]}] unless hash[:text].blank?
|
46
|
+
end.join("\n\n")
|
47
|
+
if md.blank?
|
48
|
+
""
|
49
|
+
else
|
50
|
+
"## Reference Values\n" << md
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def other_types!
|
55
|
+
raise "Unhandled methods types: #{item_types}" unless item_types.empty?
|
56
|
+
end
|
57
|
+
|
58
|
+
def nothing_to_display?
|
59
|
+
[instances_methods, class_methods, null_methods].all?(&:empty?)
|
60
|
+
end
|
35
61
|
end
|
36
62
|
end
|
@@ -9,12 +9,12 @@ class Summary
|
|
9
9
|
def title
|
10
10
|
ancestors = subject.ancestors.select do |klass|
|
11
11
|
klass.is_a?(Class) && ![BasicObject, Object, subject].include?(klass)
|
12
|
-
end
|
12
|
+
end.sort_by { |klass| klass.name }
|
13
13
|
[format_class(subject), *ancestors.map { |a| create_link(a) }].join(" < ")
|
14
14
|
end
|
15
15
|
|
16
16
|
def summary
|
17
|
-
descendants = ObjectSpace.each_object(Class).select { |klass| klass < subject && !klass.name.include?("InstanceToClassMethods") }
|
17
|
+
descendants = ObjectSpace.each_object(Class).select { |klass| klass < subject && !klass.name.include?("InstanceToClassMethods") }.sort_by { |klass| klass.name }
|
18
18
|
|
19
19
|
descendants_links = descendants.map { |d| create_link(d) }.join(", ")
|
20
20
|
"Descendants: #{descendants_links}" if descendants.count >= 1
|
@@ -44,7 +44,7 @@ module MarkdownRubyDocumentation
|
|
44
44
|
using
|
45
45
|
)
|
46
46
|
|
47
|
-
attr_reader :ruby_class, :methods, :erb_methods_class, :current_method
|
47
|
+
attr_reader :ruby_class, :methods, :erb_methods_class, :current_method, :output_object, :load_path
|
48
48
|
|
49
49
|
def parser
|
50
50
|
@parser ||= methods.each_with_object({}) do |method, hash|
|
@@ -64,7 +64,7 @@ module MarkdownRubyDocumentation
|
|
64
64
|
|
65
65
|
module CommentMacros
|
66
66
|
include Parsing
|
67
|
-
|
67
|
+
attr_accessor :output_object
|
68
68
|
# @param [String] str
|
69
69
|
# @example
|
70
70
|
# @return [String] of any comments proceeding a method def
|
@@ -184,27 +184,12 @@ module MarkdownRubyDocumentation
|
|
184
184
|
gsub_replacement(source_code, conversions, proc: proc)
|
185
185
|
end
|
186
186
|
|
187
|
-
def readable_ruby_numbers(source_code,
|
187
|
+
def readable_ruby_numbers(source_code, proc: -> (value) { ActiveSupport::NumberHelper.number_to_delimited(value) })
|
188
188
|
source_code.gsub(/([0-9][0-9_]+[0-9]+)/) do |match|
|
189
|
-
|
190
|
-
if block_given?
|
191
|
-
block.call(value)
|
192
|
-
else
|
193
|
-
ActiveSupport::NumberHelper.number_to_delimited(value)
|
194
|
-
end
|
189
|
+
proc.call(eval(match))
|
195
190
|
end
|
196
191
|
end
|
197
192
|
|
198
|
-
def include_code(include, text, &do_action)
|
199
|
-
if include.nil? || (include.present? && include.include?(remove_quotes(text)))
|
200
|
-
do_action.call(text)
|
201
|
-
else
|
202
|
-
text
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
private :include_code
|
207
|
-
|
208
193
|
def convert_early_return_to_if_else(source_code, *)
|
209
194
|
source_code = source_code.gsub(/(.+) if (.+)/, "if \\2\n\\1\nend")
|
210
195
|
source_code.gsub(/(.+) unless (.+)/, "unless \\2\n\\1\nend")
|
@@ -235,24 +220,110 @@ module MarkdownRubyDocumentation
|
|
235
220
|
[link_ref.split("/").last.split("#").last.to_s.humanize, link_ref]
|
236
221
|
end
|
237
222
|
|
238
|
-
|
239
|
-
|
240
|
-
|
223
|
+
UnimplementedMethod = Class.new(StandardError)
|
224
|
+
# @param [Class, String, Pathname] klass_or_path
|
225
|
+
# 1. String or Class representing a method reference
|
226
|
+
# 2. Pathname representing the full path of the file location a method is defined
|
227
|
+
# @param [String] title is the link display value
|
228
|
+
# @return [String, Symbol] Creates link to a given generated markdown file or returns :non_project_location message.
|
229
|
+
# 1. "[title](path/to/markdown/file.md#method-name)"
|
230
|
+
# 2. :non_project_location
|
231
|
+
def link_to_markdown(klass_or_path, title:, _ruby_class: ruby_class)
|
232
|
+
if klass_or_path.is_a?(String) || klass_or_path.is_a?(Class) || klass_or_path.is_a?(Module)
|
233
|
+
link_to_markdown_method_reference(method_reference: klass_or_path, title: title, ruby_class: _ruby_class)
|
234
|
+
elsif klass_or_path.is_a?(Pathname)
|
235
|
+
link_to_markdown_full_path(path: klass_or_path, title: title, ruby_class: _ruby_class)
|
236
|
+
else
|
237
|
+
raise ArgumentError, "invalid first arg given: #{klass_or_path} for #{__method__}"
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def link_to_markdown_method_reference(method_reference:, title:, ruby_class:)
|
242
|
+
method = MarkdownRubyDocumentation::Method.create(method_reference, null_method: true, context: ruby_class)
|
243
|
+
parts = method.context_name.to_s.split("::").reject(&:blank?)
|
244
|
+
path = parts.map { |p| p.underscore }.join("/")
|
245
|
+
path = "#{path}.md#{method.type_symbol}#{method.name}"
|
246
|
+
format_link title, MarkdownRubyDocumentation::GitHubLink::FileUrl.new(file_path: File.join(MarkdownRubyDocumentation::Generate.output_object.relative_dir, path)).to_s
|
247
|
+
end
|
248
|
+
|
249
|
+
def link_to_markdown_full_path(path:, title:, ruby_class:)
|
250
|
+
if path.to_s.include?(MarkdownRubyDocumentation::Generate.load_path)
|
251
|
+
relative_path = path.to_s.gsub(MarkdownRubyDocumentation::Generate.load_path, "")
|
252
|
+
const_nest, meth = relative_path.split("#")
|
253
|
+
const = const_nest.split("/").map(&:camelize).join("::")
|
254
|
+
link_to_markdown_method_reference(method_reference: "#{const.gsub(".rb", "")}##{meth}", title: title, ruby_class: ruby_class)
|
255
|
+
else
|
256
|
+
:non_project_location
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
class MethodLink
|
261
|
+
RUBY_METHOD_REGEX = /(\b(?<!['"])[a-z_][a-z_0-9?!]*(?!['"]))/.freeze
|
262
|
+
|
263
|
+
def initialize(match:,
|
264
|
+
call_on_title: :titleize,
|
265
|
+
method_to_class: {},
|
266
|
+
link_to_markdown:,
|
267
|
+
ruby_class:)
|
268
|
+
@match = match
|
269
|
+
@ruby_class = ruby_class
|
270
|
+
@call_on_title = call_on_title
|
271
|
+
@method_to_class = method_to_class
|
272
|
+
@link_to_markdown = link_to_markdown
|
273
|
+
end
|
274
|
+
|
275
|
+
def link
|
276
|
+
if constant_override
|
277
|
+
constant_override_method_path
|
278
|
+
else
|
279
|
+
link = link_to_markdown.call(method_path, title: title)
|
280
|
+
if link == :non_project_location
|
281
|
+
match
|
282
|
+
else
|
283
|
+
link
|
284
|
+
end
|
285
|
+
end
|
286
|
+
rescue UnimplementedMethod => e
|
287
|
+
"[#{title}](##{match.downcase.dasherize.delete(" ").delete('?')})"
|
288
|
+
end
|
289
|
+
|
290
|
+
private
|
291
|
+
|
292
|
+
attr_reader :match, :ruby_class, :call_on_title, :method_to_class, :link_to_markdown
|
293
|
+
|
294
|
+
def title
|
295
|
+
@title ||= if call_on_title
|
296
|
+
@call_on_title = [*call_on_title].compact
|
297
|
+
match.public_send(call_on_title.first, *call_on_title[1..-1])
|
298
|
+
else
|
299
|
+
match
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def constant_override
|
304
|
+
@constant_override ||= method_to_class[match.to_sym]
|
305
|
+
end
|
306
|
+
|
307
|
+
def method_path
|
308
|
+
Pathname(Method.create("##{match}", context: ruby_class).to_proc.source_location.first+"##{match}")
|
309
|
+
end
|
310
|
+
|
311
|
+
def constant_override_method_path
|
312
|
+
method_object = Method.create("##{match}", context: constant_override)
|
313
|
+
link_to_markdown.call("#{method_object.context.name}##{method_object.name}", title: title)
|
314
|
+
end
|
241
315
|
end
|
242
316
|
|
243
317
|
def methods_as_local_links(ruby_source,
|
244
318
|
call_on_title: :titleize,
|
245
|
-
|
246
|
-
ruby_source.gsub(
|
319
|
+
method_to_class: {})
|
320
|
+
ruby_source.gsub(MethodLink::RUBY_METHOD_REGEX) do |match|
|
247
321
|
if is_a_method_on_ruby_class?(match)
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
match
|
254
|
-
end
|
255
|
-
proc.call(title, "##{match.downcase.dasherize.delete(" ").delete('?')}")
|
322
|
+
MethodLink.new(match: match,
|
323
|
+
ruby_class: ruby_class,
|
324
|
+
call_on_title: call_on_title,
|
325
|
+
method_to_class: method_to_class,
|
326
|
+
link_to_markdown: method(:link_to_markdown)).link
|
256
327
|
else
|
257
328
|
match
|
258
329
|
end
|
@@ -278,8 +349,8 @@ module MarkdownRubyDocumentation
|
|
278
349
|
|
279
350
|
def ruby_if_statement_to_md(ruby_source, proc: false)
|
280
351
|
conversions = {
|
281
|
-
/else if(.*)/ => "*
|
282
|
-
/elsif(.*)/ => "*
|
352
|
+
/else if(.*)/ => "* __Else If__\\1\n__Then__",
|
353
|
+
/elsif(.*)/ => "* __Else If__\\1\n__Then__",
|
283
354
|
/if(.*)/ => "* __If__\\1\n__Then__",
|
284
355
|
/unless(.*)/ => "* __Unless__\\1\n__Then__",
|
285
356
|
"else" => "* __Else__"
|
@@ -13,6 +13,14 @@ module MarkdownRubyDocumentation
|
|
13
13
|
method
|
14
14
|
end
|
15
15
|
|
16
|
+
ruby_class.send(:define_singleton_method, :output_object) do
|
17
|
+
output_object
|
18
|
+
end
|
19
|
+
|
20
|
+
ruby_class.send(:define_singleton_method, :load_path) do
|
21
|
+
load_path
|
22
|
+
end
|
23
|
+
|
16
24
|
ruby_class.extend(CommentMacros)
|
17
25
|
|
18
26
|
erb = ERB.new(str, nil, "-")
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module MarkdownRubyDocumentation
|
2
2
|
class WriteMarkdownToDisk
|
3
3
|
|
4
|
-
attr_reader :dir, :skip_if_blank
|
4
|
+
attr_reader :dir, :skip_if_blank, :relative_dir
|
5
5
|
|
6
|
-
def initialize(dir:, skip_if_blank: false)
|
6
|
+
def initialize(dir:, skip_if_blank: false, relative_dir:)
|
7
7
|
@dir = dir
|
8
8
|
@skip_if_blank = skip_if_blank
|
9
|
+
@relative_dir = relative_dir
|
9
10
|
end
|
10
11
|
|
11
12
|
def call(name:, text:)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: markdown_ruby_documentation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dustin Zeisler
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-04-
|
11
|
+
date: 2016-04-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: method_source
|