docs: def generate_changelog(from_version: str, to_version: str = None) -> dict:
      """
      Generates a changelog for the given version.
  
      :param from_version: The last version not in the changelog. The changelog
                           will be generated from the commit after this one.
      :param to_version: The last version in the changelog.
      :return: a dict with different changelog sections
      """
      debug('generate_changelog("{}", "{}")'.format(from_version, to_version))
      changes: dict = {'feature': [], 'fix': [],
                       'documentation': [], 'refactor': [], 'breaking': []}
  
      found_the_release = to_version is None
  
      rev = None
      if from_version:
          rev = 'v{0}'.format(from_version)
  
      for _hash, commit_message in get_commit_log(rev):
          if not found_the_release:
              if to_version and to_version not in commit_message:
                  continue
              else:
                  found_the_release = True
  
          if from_version is not None and from_version in commit_message:
              break
  
          try:
              message = current_commit_parser()(commit_message)
              if message[1] not in changes:
                  continue
  
              changes[message[1]].append((_hash, message[3][0]))
  
              if message[3][1] and 'BREAKING CHANGE' in message[3][1]:
                  parts = re_breaking.match(message[3][1])
                  if parts:
                      changes['breaking'].append(parts.group(1))
  
              if message[3][2] and 'BREAKING CHANGE' in message[3][2]:
                  parts = re_breaking.match(message[3][2])
                  if parts:
                      changes['breaking'].append(parts.group(1))
  
          except UnknownCommitMessageStyleError as err:
              debug('Ignoring', err)
              pass
  
      return changes