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,
  :question_mark_method_format,
  :methods_as_local_links,
  :remove_end_keyword,
  :constants_with_name_and_value,
  :remove_memoized_vars,
  :comment_format
]
UnimplementedMethod =
Class.new(StandardError)

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Parsing

#extract_dsl_comment, #extract_dsl_comment_from_method, #insert_method_name, #parse_erb, #ruby_class_meth_comment, #ruby_class_meth_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



385
386
387
388
389
390
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 385

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

#comment_format(source_code, proc: false) ⇒ Object



151
152
153
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 151

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

#constants_with_name_and_value(ruby_source) ⇒ Object



337
338
339
340
341
342
343
344
345
346
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 337

def constants_with_name_and_value(ruby_source, *)
  ruby_source.gsub(/([A-Z]+[A-Z_0-9]+)/) do |match|
    begin
      value = ruby_class.const_get(match)
      "[#{ConstantsPresenter.format(value)}](##{match.dasherize.downcase})"
    rescue NameError
      match
    end
  end
end

#convert_early_return_to_if_else(source_code) ⇒ Object



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

def convert_early_return_to_if_else(source_code, *)
  source_code = source_code.gsub(/(.+) if (.+)/, "if \\2\n\\1\nend")
  source_code.gsub(/(.+) unless (.+)/, "unless \\2\n\\1\nend")
end

#elsif_to_else_if(source_code, proc: false) ⇒ Object



166
167
168
169
170
171
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 166

def elsif_to_else_if(source_code, 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



214
215
216
217
218
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 214

def format_link(title, link_ref)
  path, anchor   = *link_ref.to_s.split("#")
  formatted_path = [path, anchor.try!(:dasherize).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



377
378
379
380
381
382
383
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 377

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)

    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



235
236
237
238
239
240
241
242
243
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 235

def link_to_markdown(klass_or_path, title:, _ruby_class: 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


253
254
255
256
257
258
259
260
261
262
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 253

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


245
246
247
248
249
250
251
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 245

def link_to_markdown_method_reference(method_reference:, title:, 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



392
393
394
395
396
397
398
399
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 392

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


321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 321

def methods_as_local_links(ruby_source,
                           call_on_title: :titleize,
                           method_to_class: {})
  ruby_source.gsub(MethodLink::RUBY_METHOD_REGEX) do |match|
    if is_a_method_on_ruby_class?(match)
      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
    else
      match
    end
  end
end

#nil_check_readable(source_code, proc: false) ⇒ Object



159
160
161
162
163
164
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 159

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

#pretty_early_return(source_code) ⇒ Object



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

def pretty_early_return(source_code, *)
  source_code.gsub(/return (unless|if)/, 'return nothing \1')
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



348
349
350
351
352
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 348

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, proc: -> (value) { ActiveSupport::NumberHelper.number_to_delimited(value) }) ⇒ Object



191
192
193
194
195
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 191

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

#remove_colons(source_code) ⇒ Object



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

def remove_colons(source_code)
  source_code.gsub(":", '')
end

#remove_end_keyword(ruby_source) ⇒ Object



354
355
356
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 354

def remove_end_keyword(ruby_source, *)
  ruby_source.gsub(/^[\s]*end\n?/, "")
end

#remove_memoized_vars(source_code = print_method_source) ⇒ Object



155
156
157
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 155

def remove_memoized_vars(source_code=print_method_source, *)
  source_code.gsub(/@[a-z][a-z0-9_]+ \|\|=?\s/, "") # @memoized_vars ||=
end

#ruby_case_statement_to_md(ruby_source, proc: false) ⇒ Object



368
369
370
371
372
373
374
375
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 368

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



358
359
360
361
362
363
364
365
366
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 358

def ruby_if_statement_to_md(ruby_source, proc: false)
  conversions = {
    /elsif(.*)/         => "* __Else If__\\1\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, proc: false) ⇒ Object



177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 177

def ruby_operators_to_english(source_code, 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"
  }

  gsub_replacement(source_code, conversions, proc: proc)
end

#ruby_to_markdown(*args) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 135

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, {})
    ruby_source = send(processor, ruby_source, options) if options
  end
  ruby_source
end

#ternary_to_if_else(ternary) ⇒ Object



206
207
208
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 206

def ternary_to_if_else(ternary, *)
  ternary.gsub(/(.*) \? (.*) \: (.*)/, "if \\1\n\\2\nelse\n\\3\nend")
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



223
224
225
# File 'lib/markdown_ruby_documentation/template_parser.rb', line 223

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