class Changelog::Notifier::Parsers::Markdown

Parses the given `content` as Markdown following the specifications from keepachangelog.com.

Public Class Methods

new(content) click to toggle source
# File lib/changelog/notifier/parsers/markdown.rb, line 11
def initialize(content)
  @content = content
end

Public Instance Methods

extract(version) click to toggle source
# File lib/changelog/notifier/parsers/markdown.rb, line 15
def extract(version)
  version_is_valid?(version) || raise(ArgumentError, 'Invalid version')

  parse!

  version_release_note = detect_version_release_note_for(version)
  version_release_note || raise(Changelog::Notifier::ReleaseNoteNotFound)

  version_release_note_hash = create_hash_from(version_release_note)

  url = fetch_version_url_for(version)
  version_release_note_hash[:url] = url

  version_release_note_hash
end

Private Instance Methods

change_types() click to toggle source

See keepachangelog.com/en/1.0.0/#how

# File lib/changelog/notifier/parsers/markdown.rb, line 34
def change_types
  %w[
    added
    changed
    deprecated
    removed
    fixed
    security
  ]
end
create_hash_from(version_release_note) click to toggle source
# File lib/changelog/notifier/parsers/markdown.rb, line 45
def create_hash_from(version_release_note)
  sections = version_release_note.split('### ')

  # Removes trailing whitespaces
  sections = sections.map { |section| section.gsub(/\s+$/, '') }

  version, date = extract_version_and_date_from(sections.shift)

  changes = extract_actions_from(sections)

  { version: version, date: date, changes: changes }
end
detect_version_release_note_for(version) click to toggle source
# File lib/changelog/notifier/parsers/markdown.rb, line 58
def detect_version_release_note_for(version)
  version_number = fetch_version_number_from(version)

  @versions.detect do |changelog_version|
    changelog_version.start_with?("#{version_number}]") ||
      changelog_version.start_with?("#{version}]")
  end
end
extract_actions_from(sections) click to toggle source
# File lib/changelog/notifier/parsers/markdown.rb, line 67
def extract_actions_from(sections)
  sections.each_with_object({}) do |section, accumulator|
    type, logs = section.match(/^(#{change_types.join('|')})\n(.*)/mi)
                       &.captures

    next unless type

    type = type.downcase.to_sym

    logs = logs.split(/\s+-/)
               .reject(&:empty?)
               .map { |log| log.gsub(/^\s+/, '') }
               .map { |log| log.gsub("\n", ' ') }

    accumulator[type] = logs
  end
end
extract_version_and_date_from(section) click to toggle source
# File lib/changelog/notifier/parsers/markdown.rb, line 85
def extract_version_and_date_from(section)
  section.match(/([\d\.]+)\]\s+-\s+([\d+-]+)/)&.captures
end
fetch_version_number_from(version) click to toggle source
# File lib/changelog/notifier/parsers/markdown.rb, line 89
def fetch_version_number_from(version)
  version.match(/([\d\.]+)/)&.captures&.first
end
fetch_version_url_for(version) click to toggle source
# File lib/changelog/notifier/parsers/markdown.rb, line 93
def fetch_version_url_for(version)
  version_number = fetch_version_number_from(version)
  @content.match(%r{\[#{version_number}\]: (https://[\S]+)})
         &.captures
         &.first
end
parse!() click to toggle source

Split the file on the double dashes, representing version sections.

# File lib/changelog/notifier/parsers/markdown.rb, line 103
def parse!
  @versions = @content.split(/##\s\[/)
end
version_is_valid?(version) click to toggle source
# File lib/changelog/notifier/parsers/markdown.rb, line 107
def version_is_valid?(version)
  version =~ /[\d\.]+/
end