class Ollama::Utils::ANSIMarkdown

def self.parse(source)

def self.parse(source)
  @doc = Kramdown::Document.new(
    source, input: :mygfm, auto_ids: false, entity_output: :as_char
  ).to_ansi
end

def convert(el, opts = {})

def convert(el, opts = {})
  send("convert_#{el.type}", el, opts)
end

def convert_a(el, opts)

def convert_a(el, opts)
  url = el.attr['href']
  hyperlink(url) { inner(el, opts) }
end

def convert_blank(_el, opts)

def convert_blank(_el, opts)
  opts[:result] =~ /\n\n\Z|\A\Z/ ? "" : "\n"
end

def convert_blockquote(el, opts)

def convert_blockquote(el, opts)
  newline ?โ€œ + inner(el, opts).sub(/\n+\z/, '') + ?โ€
end

def convert_br(_el, opts)

def convert_br(_el, opts)
  ''
end

def convert_codeblock(el, _opts)

def convert_codeblock(el, _opts)
  blue { el.value }
end

def convert_codespan(el, _opts)

def convert_codespan(el, _opts)
  blue { el.value }
end

def convert_em(el, opts)

def convert_em(el, opts)
  italic { inner(el, opts) }
end

def convert_entity(el, _opts)

def convert_entity(el, _opts)
  el.value.char
end

def convert_header(el, opts)

def convert_header(el, opts)
  newline bold { underline { inner(el, opts) } }
end

def convert_hr(_el, _opts)

def convert_hr(_el, _opts)
  newline ?โ”€ * width(percentage: 100)
end

def convert_html_element(el, opts)

def convert_html_element(el, opts)
  if el.value == 'i' || el.value == 'em'
    italic { inner(el, opts) }
  elsif el.value == 'b' || el.value == 'strong'
    bold { inner(el, opts) }
  else
    ''
  end
end

def convert_img(el, _opts)

def convert_img(el, _opts)
  url = el.attr['src']
  alt = el.attr['alt']
  alt.strip.size == 0 and alt = url
  alt = '๐Ÿ–ผ ' + alt
  hyperlink(url) { alt }
end

def convert_li(el, opts)

def convert_li(el, opts)
  opts = opts.dup
  opts[:list_indent] = 2 + opts[:list_indent].to_i
  newline inner(el, opts).sub(/\n+\Z/, '')
end

def convert_ol(el, opts)

def convert_ol(el, opts)
  list_indent = opts[:list_indent].to_i
  inner(el, opts) { |_inner_el, index, content|
    result = '%u. %s' % [ index + 1, content ]
    result = newline(result, count: index <= el.children.size - 1 ? 1 : 2)
    result.gsub(/^/, ' ' * list_indent)
  }
end

def convert_p(el, opts)

def convert_p(el, opts)
  length = width(percentage: 90) - opts[:list_indent].to_i
  length < 0 and return ''
  newline wrap(inner(el, opts), length:)
end

def convert_root(el, opts)

def convert_root(el, opts)
  inner(el, opts)
end

def convert_smart_quote(el, _opts)

def convert_smart_quote(el, _opts)
  el.value.to_s =~ /[rl]dquo/ ? "\"" : "'"
end

def convert_strong(el, opts)

def convert_strong(el, opts)
  bold { inner(el, opts) }
end

def convert_table(el, opts)

def convert_table(el, opts)
  table = Terminal::Table.new
  table.style = {
    all_separators: true,
    border: :unicode_round,
  }
  opts[:table] = table
  inner(el, opts)
  el.options[:alignment].each_with_index do |a, i|
    a == :default and next
    opts[:table].align_column(i, a)
  end
  newline table.to_s
end

def convert_tbody(el, opts)

def convert_tbody(el, opts)
  res = +''
  res << inner(el, opts)
end

def convert_td(el, opts)

def convert_td(el, opts)
  inner(el, opts)
end

def convert_text(el, _opts)

def convert_text(el, _opts)
  el.value
end

def convert_tfoot(el, opts)

def convert_tfoot(el, opts)
  ''
end

def convert_thead(el, opts)

def convert_thead(el, opts)
  rows = inner(el, opts)
  rows = rows.split(/\s*\|\s*/)[1..].map(&:strip)
  opts[:table].headings = rows
  ''
end

def convert_tr(el, opts)

def convert_tr(el, opts)
  return '' if el.children.empty?
  full_width = width(percentage: 90)
  cols = el.children.map { |c| convert(c, opts).strip }
  row_size = cols.sum(&:size)
  return '' if row_size.zero?
  opts[:table] << cols.map { |c|
    length = (full_width * (c.size / row_size.to_f)).floor
    wrap(c, length:)
  }
  ''
end

def convert_ul(el, opts)

def convert_ul(el, opts)
  list_indent = opts[:list_indent].to_i
  inner(el, opts) { |_inner_el, index, content|
    result = 'ยท %s' % content
    result = newline(result, count: index <= el.children.size - 1 ? 1 : 2)
    result.gsub(/^/, ' ' * list_indent)
  }
end

def convert_xml_comment(*)

def convert_xml_comment(*)
  ''
end

def convert_xml_pi(*)

def convert_xml_pi(*)
  ''
end

def initialize(root, options)

def initialize(root, options)
  super
end

def inner(el, opts, &block)

def inner(el, opts, &block)
  result = +''
  options = opts.dup.merge(parent: el)
  el.children.each_with_index do |inner_el, index|
    options[:index] = index
    options[:result] = result
    begin
      content = send("convert_#{inner_el.type}", inner_el, options)
      result << (block&.(inner_el, index, content) || content)
    rescue NameError => e
      warning "Caught #{e.class} for #{inner_el.type}"
    end
  end
  result
end

def newline(text, count: 1)

def newline(text, count: 1)
  text.gsub(/\n*\z/, ?\n * count)
end