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