Module: MarkdownRubyDocumentation::TemplateParser::CommentMacros

Includes:
Parsing
Included in:
MarkdownRubyDocumentation::TemplateParser
Defined in:
lib/markdown_ruby_documentation/template_parser.rb

Defined Under Namespace

Classes: MethodLink

Constant Summary collapse

RUBY_TO_MARKDOWN_PROCESSORS =
[
  :readable_ruby_numbers,
  :pretty_early_return,
  :convert_early_return_to_if_else,
  :ternary_to_if_else,
  :ruby_if_statement_to_md,
  :ruby_case_statement_to_md,
  :ruby_operators_to_english,
  :nil_check_readable,
  :boolean_blocks,
  :question_mark_method_format,
  :symbol_to_proc,
  :methods_as_local_links,
  :remove_end_keyword,
  :constants_with_name_and_value,
  :remove_memoized_vars,
  :comment_format,
  :rescue_format,
]
UnimplementedMethod =
Class.new(StandardError)
IGNORE_METHOD_OWNERS =
[
  Object
]

Constants included from Parsing

Parsing::CLASS_MACROS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Parsing

#extract_dsl_comment, #extract_dsl_comment_from_method, #get_line_number, #insert_method_name, #look_for_class_macro_comment, #parse_erb, #ruby_class_meth_comment, #ruby_class_meth_source_location, #source_location, #strip_comment_hash, #when_only_start, #when_start_and_end

Instance Attribute Details

#output_objectObject

Returns the value of attribute output_object.



66
67
68
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 66

def output_object
  @output_object
end

Instance Method Details

#array_to_markdown_table(array, key_name:) ⇒ Object



466
467
468
469
470
471
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 466

def array_to_markdown_table(array, key_name:)
  key_max_length = [array.group_by(&:size).max.first, key_name.size + 1].max
  header         = markdown_table_header([[key_name, key_max_length+3]])
  rows           = array.map { |key| "| #{key.to_s.ljust(key_max_length)} |" }.join("\n")
  [header, rows].join("\n")
end

#boolean_blocks(source_code = print_method_source, proc: false) ⇒ Object



163
164
165
166
167
168
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 163

def boolean_blocks(source_code=print_method_source, proc: false)
  gsub_replacement(source_code, {
    /(.*)\.any\?\s*do\s\|.*\|/ => "Are there any \\1 where\n",
    /(.*)\.all\?\s*do\s\|.*\|/ => "Do all \\1 have\n",
  }, proc: proc)
end

#comment_format(source_code = print_method_source, proc: false) ⇒ Object



177
178
179
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 177

def comment_format(source_code=print_method_source, proc: false)
  gsub_replacement(source_code, { /^#(.*)/ => "</br>*(\\1)*</br>" }, proc: proc)
end

#constants_with_name_and_value(ruby_source, proc: false) ⇒ Object



404
405
406
407
408
409
410
411
412
413
414
415
416
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 404

def constants_with_name_and_value(ruby_source, proc: false)
  ruby_source.gsub(/([A-Z]+[A-Z_0-9]+)/) do |match|
    begin
      value           = ruby_class.const_get(match)
      link            = "##{match.dasherize.downcase}"
      formatted_value = ConstantsPresenter.format(value)
      replacement     = format_link(formatted_value, link)
      proc ? proc.call(replacement, match, { value: value, link: link, formatted_value: formatted_value }) : replacement
    rescue NameError
      match
    end
  end
end

#convert_early_return_to_if_else(source_code = print_method_source, proc: false) ⇒ Object



233
234
235
236
237
238
239
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 233

def convert_early_return_to_if_else(source_code=print_method_source, proc: false)
  conversions = {
    /(.+) if (.+)/   => "if \\2\n\\1\nend",
    /(.+) unless (.+)/ => "unless \\2\n\\1\nend"
  }
  gsub_replacement(source_code, conversions, proc: proc)
end

#default_title(klass_or_path, _ruby_class) ⇒ Object



292
293
294
295
296
297
298
299
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 292

def default_title(klass_or_path, _ruby_class)
  method = MarkdownRubyDocumentation::Method.create(klass_or_path, null_method: true, context: _ruby_class)
  if method.name
    method.name
  else
    method.context_name.to_s.demodulize
  end.to_s.titleize
end

#elsif_to_else_if(source_code = print_method_source, proc: false) ⇒ Object



195
196
197
198
199
200
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 195

def elsif_to_else_if(source_code=print_method_source, proc: false)
  conversions = {
    "elsif" => "else if"
  }
  gsub_replacement(source_code, conversions, proc: proc)
end

#eval_method(str = current_method) ⇒ Object

Returns anything that the evaluated method would return.

Parameters:

  • str (String) (defaults to: current_method)

Returns:

  • (Object)

    anything that the evaluated method would return.



85
86
87
88
89
90
91
92
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 85

def eval_method(str=current_method)
  case (method = Method.create(str, context: ruby_class))
  when ClassMethod
    method.context.public_send(method.name)
  when InstanceMethod
    InstanceToClassMethods.new(method: method).eval_instance_method
  end
end

Examples:

format_link(“MyLink”, “path/to/it#method_name?”)

#=> "[MyLink](#path/to/it#method-name)"

Parameters:

  • title (String)

    the name of the link

  • link_ref (String)

    the url with method anchor



259
260
261
262
263
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 259

def format_link(title, link_ref)
  path, anchor   = *link_ref.to_s.split("#")
  formatted_path = [path, anchor.try!(:dasherize).try!(:delete, "?").try(:delete, "!")].compact.join("#")
  "[#{title}](#{formatted_path})"
end

#git_hub_file_url(file_path_or_const) ⇒ Object



108
109
110
111
112
113
114
115
116
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 108

def git_hub_file_url(file_path_or_const)
  if file_path_or_const.include?("/")
    GitHubLink::FileUrl.new(file_path: file_path_or_const)
  else
    const    = Object.const_get(file_path_or_const)
    a_method = const.public_instance_methods.first
    git_hub_method_url("#{file_path_or_const}##{a_method}")
  end
end

#git_hub_method_url(method_reference = current_method) ⇒ Object

Parameters:

  • method_reference (String) (defaults to: current_method)


103
104
105
106
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 103

def git_hub_method_url(method_reference=current_method)
  method = Method.create(method_reference.dup, context: ruby_class)
  GitHubLink::MethodUrl.new(subject: method.context, method_object: method)
end

#hash_to_markdown_table(hash, key_name:, value_name:) ⇒ Object



458
459
460
461
462
463
464
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 458

def hash_to_markdown_table(hash, key_name:, value_name:)
  key_max_length   = [hash.keys.group_by(&:size).max.first, key_name.size + 1].max
  value_max_length = [hash.values.group_by { |v| v.try!(:size) || 1 }.max.first, value_name.size + 1].max
  header           = markdown_table_header([[key_name, key_max_length+2], [value_name, value_max_length+2]])
  rows             = hash.map { |key, value| "| #{key.to_s.ljust(key_max_length)} | #{value.to_s.ljust(value_max_length)}|" }.join("\n")
  [header, rows].join("\n")
end

Returns Creates link to a given generated markdown file or returns :non_project_location message.

  1. “[title](path/to/markdown/file.md#method-name)”

  2. :non_project_location.

Parameters:

  • klass_or_path (Class, String, Pathname)
    1. String or Class representing a method reference

    2. Pathname representing the full path of the file location a method is defined

  • title (String) (defaults to: default_title(klass_or_path, _ruby_class))

    is the link display value

Returns:

  • (String, Symbol)

    Creates link to a given generated markdown file or returns :non_project_location message.

    1. “[title](path/to/markdown/file.md#method-name)”

    2. :non_project_location



280
281
282
283
284
285
286
287
288
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 280

def link_to_markdown(klass_or_path, _ruby_class: ruby_class, title: default_title(klass_or_path, _ruby_class))
  if klass_or_path.is_a?(String) || klass_or_path.is_a?(Class) || klass_or_path.is_a?(Module)
    link_to_markdown_method_reference(method_reference: klass_or_path, title: title, ruby_class: _ruby_class)
  elsif klass_or_path.is_a?(Pathname)
    link_to_markdown_full_path(path: klass_or_path, title: title, ruby_class: _ruby_class)
  else
    raise ArgumentError, "invalid first arg given: #{klass_or_path} for #{__method__}"
  end
end


314
315
316
317
318
319
320
321
322
323
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 314

def link_to_markdown_full_path(path:, title:, ruby_class:)
  if path.to_s.include?(MarkdownRubyDocumentation::Generate.load_path)
    relative_path    = path.to_s.gsub(MarkdownRubyDocumentation::Generate.load_path, "")
    const_nest, meth = relative_path.split("#")
    const            = const_nest.split("/").map(&:camelize).join("::")
    link_to_markdown_method_reference(method_reference: "#{const.gsub(".rb", "")}##{meth}", title: title, ruby_class: ruby_class)
  else
    :non_project_location
  end
end


305
306
307
308
309
310
311
312
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 305

def link_to_markdown_method_reference(method_reference:, title:, ruby_class:)
  return title if IGNORE_METHOD_OWNERS.include?(ruby_class)
  method = MarkdownRubyDocumentation::Method.create(method_reference, null_method: true, context: ruby_class)
  parts  = method.context_name.to_s.split("::").reject(&:blank?)
  path   = parts.map { |p| p.underscore }.join("/")
  path   = "#{path}.md#{method.type_symbol}#{method.name}"
  format_link title, MarkdownRubyDocumentation::GitHubLink::FileUrl.new(file_path: File.join(MarkdownRubyDocumentation::Generate.output_object.relative_dir, path)).to_s
end

#markdown_table_header(array_headers) ⇒ Object



473
474
475
476
477
478
479
480
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 473

def markdown_table_header(array_headers)
  parts      = array_headers.map { |header, pad_length=0| " #{header.ljust(pad_length-1)}" }
  bar        = parts.map(&:length).map { |length| ("-" * (length)) }.join("|")
  bar[-1]    = "|"
  header     = parts.join("|")
  header[-1] = "|"
  [("|" + header), ("|" + bar)].join("\n")
end


386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 386

def methods_as_local_links(ruby_source,
                           call_on_title: :titleize,
                           method_to_class: {},
                           proc: false)
  ruby_source.gsub(MethodLink::RUBY_METHOD_REGEX) do |match|
    if is_a_method_on_ruby_class?(match, method_to_class[match.to_sym] || ruby_class)
      replacement = MethodLink.new(match:            match,
                                   ruby_class:       ruby_class,
                                   call_on_title:    call_on_title,
                                   method_to_class:  method_to_class,
                                   link_to_markdown: method(:link_to_markdown)).link
      proc ? proc.call(replacement, match) : replacement
    else
      match
    end
  end
end

#nil_check_readable(source_code = print_method_source, proc: false) ⇒ Object



188
189
190
191
192
193
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 188

def nil_check_readable(source_code=print_method_source, proc: false)
  conversions = {
    ".nil?" => " is missing?"
  }
  gsub_replacement(source_code, conversions, proc: proc)
end

#pretty_early_return(source_code = print_method_source, proc: false) ⇒ Object



241
242
243
244
245
246
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 241

def pretty_early_return(source_code=print_method_source, proc: false)
  conversions = {
    /return (unless|if)/   => 'return nothing \1'
  }
  gsub_replacement(source_code, conversions, proc: proc)
end

Parameters:

  • str (String)

Returns:

  • (String)


77
78
79
80
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 77

def print_mark_doc_from(str)
  method = Method.create(str, context: ruby_class)
  parse_erb(insert_method_name(extract_dsl_comment(print_raw_comment(str)), method), method)
end

Returns the source of a method block is returned as text.

Parameters:

  • method_reference (String) (defaults to: current_method)

Returns:

  • (String)

    the source of a method block is returned as text.



96
97
98
99
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 96

def print_method_source(method_reference=current_method)
  method = Method.create(method_reference.dup, context: ruby_class)
  PrintMethodSource.new(method: method).print
end

Returns of any comments proceeding a method def.

Parameters:

  • str (String)

Returns:

  • (String)

    of any comments proceeding a method def



70
71
72
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 70

def print_raw_comment(str)
  strip_comment_hash(ruby_class_meth_comment(Method.create(str, context: ruby_class)))
end

#question_mark_method_format(ruby_source) ⇒ Object



418
419
420
421
422
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 418

def question_mark_method_format(ruby_source, *)
  ruby_source.gsub(/(\b(?<!['"])\.[a-z_][a-z_0-9]+\?(?!['"]))/) do |match|
    " is #{match}".sub(".", "")
  end
end

#readable_ruby_numbers(source_code = print_method_source, proc: -> (replacement, _) { ActiveSupport::NumberHelper.number_to_delimited(replacement) }) ⇒ Object



227
228
229
230
231
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 227

def readable_ruby_numbers(source_code=print_method_source, proc: -> (replacement, _) { ActiveSupport::NumberHelper.number_to_delimited(replacement) })
  source_code.gsub(/([0-9][0-9_]+[0-9]+)/) do |match|
    proc.call(eval(match), match)
  end
end

#remove_colons(source_code = print_method_source, proc: false) ⇒ Object



202
203
204
205
206
207
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 202

def remove_colons(source_code=print_method_source, proc: false)
  conversions = {
    ":" => ''
  }
  gsub_replacement(source_code, conversions, proc: proc)
end

#remove_end_keyword(ruby_source, proc: false) ⇒ Object



431
432
433
434
435
436
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 431

def remove_end_keyword(ruby_source, proc: false)
  conversions = {
    /^[\s]*end\n?/ => ""
  }
  gsub_replacement(ruby_source, conversions, proc: proc)
end

#remove_memoized_vars(source_code = print_method_source, proc: false) ⇒ Object



181
182
183
184
185
186
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 181

def remove_memoized_vars(source_code=print_method_source, proc: false)
  conversions = {
    /@[a-z][a-z0-9_]+ \|\|=?\s/ => "" # @memoized_vars ||=
  }
  gsub_replacement(source_code, conversions, proc: proc)
end

#rescue_format(source_code = print_method_source, proc: false) ⇒ Object



170
171
172
173
174
175
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 170

def rescue_format(source_code=print_method_source, proc: false)
  gsub_replacement(source_code, {
    /=>\s.*/                     => "",
    /rescue ([a-zA-Z0-9::]*)./ => "Given a failure of \\1 __Then__\n",
  }, proc: proc)
end

#ruby_case_statement_to_md(ruby_source, proc: false) ⇒ Object



449
450
451
452
453
454
455
456
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 449

def ruby_case_statement_to_md(ruby_source, proc: false)
  conversions = {
    /case(.*)/ => "* __Given__\\1",
    /when(.*)/ => "* __When__\\1\n__Then__",
    "else"     => "* __Else__"
  }
  gsub_replacement(ruby_source, conversions, proc: proc)
end

#ruby_if_statement_to_md(ruby_source, proc: false) ⇒ Object



438
439
440
441
442
443
444
445
446
447
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 438

def ruby_if_statement_to_md(ruby_source, proc: false)
  conversions = {
    /elsif(.*)/                    => "* __Else If__\\1\n__Then__",
    /^\s?if(.*)\s([|&]{0,2})\n(.*)/ => "* __If__\\1 \\2 \\3\n__Then__",
    /^\s?if(.*)/                   => "* __If__\\1\n__Then__",
    /unless(.*)/                   => "* __Unless__\\1\n__Then__",
    "else"                         => "* __Else__"
  }
  gsub_replacement(ruby_source, conversions, proc: proc)
end

#ruby_operators_to_english(source_code = print_method_source, proc: false) ⇒ Object



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 209

def ruby_operators_to_english(source_code=print_method_source, proc: false)
  conversions = {
    "&&"   => "and",
    ">="   => "is greater than or equal to",
    "<="   => "is less than or equal to",
    " < "   => " is less than ",
    " > "   => " is greater than ",
    " == "  => " Equal to ",
    "||"    => "or",
    /^!!/  => "",
    /\s!!/ => " ",
    /^!/   => "*is not* ",
    /\s!/  => " *is not* "
  }

  gsub_replacement(source_code, conversions, proc: proc)
end

#ruby_to_markdown(*args) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 138

def ruby_to_markdown(*args)
  any_args           = AnyArgs.new(args:                args,
                                   print_method_source: method(:print_method_source),
                                   caller:              caller,
                                   for_method:          __method__,
                                   method_creator:      method(:create_method_with_ruby_class))
  disable_processors = any_args.disable_processors
  ruby_source        = any_args.source_code

  RUBY_TO_MARKDOWN_PROCESSORS.each do |processor|
    options     = disable_processors.fetch(processor, :enabled)
    ruby_source = case options
                  when :enabled
                    send(processor, ruby_source)
                  when Hash
                    send(processor, ruby_source, options)
                  when Proc
                    send(processor, ruby_source, proc: options)
                  else
                    ruby_source
                  end
  end
  ruby_source
end

#symbol_to_proc(ruby_source, proc: false) ⇒ Object



424
425
426
427
428
429
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 424

def symbol_to_proc(ruby_source, proc: false)
  conversions = {
    /\(&:([a-z_?!]*)\)/ => " \\1"
  }
  gsub_replacement(ruby_source, conversions, proc: proc)
end

#ternary_to_if_else(source_code = print_method_source, proc: false) ⇒ Object



248
249
250
251
252
253
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 248

def ternary_to_if_else(source_code=print_method_source, proc: false)
  conversions = {
    /(.*) \? (.*) \: (.*)/   =>  "if \\1\n\\2\nelse\n\\3\nend"
  }
  gsub_replacement(source_code, conversions, proc: proc)
end

Examples:

title_from_link“path/to/it#method_name?”)

#=> "[Method Name](#path/to/it#method-name)"

Parameters:

  • link_ref (String)

    the url with method anchor



268
269
270
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 268

def title_from_link(link_ref)
  [link_ref.split("/").last.split("#").last.to_s.humanize, link_ref]
end