Class: RubyRich::Markdown

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_rich/markdown.rb

Defined Under Namespace

Modules: Frontmatter Classes: TerminalConverter

Constant Summary collapse

MarkdownTheme =

Markdown rendering colour theme. ===

Each key maps to ‘[color, bright]` accepted by AnsiCode.

{
  heading_1:         [:cyan,     true],
  heading_2:         [:blue,     true],
  heading_3:         [:yellow,   true],
  heading_4_6:       [:black,    true],
  heading_underline: [:cyan,     true],  # H1
  heading_underline2:[:blue,     true],  # H2
  text:              [:white,    true],
  strong_text:       [:white,    true],
  code_border:       [:black,    true],
  code_bg:           [:black,    true],
  code_fg:           [:white,    true],
  inline_code_fg:    [:black,    false],
  inline_code_bg:    [:white,    false],
  blockquote_marker: [:black,    true],
  blockquote_text:   [:white,    true],
  blockquote_italic: true,
  list_level_1:      [:cyan,     true],
  list_level_2:      [:magenta,  true],
  list_level_3:      [:yellow,   true],
  ordered_list:      [:cyan,     true],
  task_checked:      [:green,    true],
  task_unchecked:    [:black,    true],
  link_text:         [:blue,     true],
  link_url:          [:black,    true],
  image_label:       [:magenta,  true],
  rule:              [:black,    true],
  footnote:          [:magenta,  true],
  abbreviation:      [:black,    true],
  math:              [:magenta,  true],
  mark_fg:           [:black,    false],
  mark_bg:           [:yellow,   false],
  kbd_fg:            [:black,    false],
  kbd_bg:            [:white,    false],
  table_border:      :simple
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Markdown

Returns a new instance of Markdown.



1359
1360
1361
# File 'lib/ruby_rich/markdown.rb', line 1359

def initialize(options = {})
  @options = options
end

Class Method Details

.render(markdown_text, options = {}) ⇒ String

渲染 Markdown 文本为 ANSI 终端输出

Parameters:

  • markdown_text (String)

    输入的 Markdown 文本

  • options (Hash) (defaults to: {})

    渲染选项

Options Hash (options):

  • :width (Integer)

    终端宽度(默认 80)

  • :indent (String)

    缩进字符串(默认 ‘ ’)

  • :table_border_style (Symbol)

    表格边框样式 (:none, :simple, :full)

  • :kramdown (Hash)

    传递给 Kramdown::Document 的额外选项

Returns:

  • (String)

    ANSI 格式的终端输出



1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
# File 'lib/ruby_rich/markdown.rb', line 1297

def self.render(markdown_text, options = {})
  converter_options = {
    width: options[:width] || 80,
    indent: options[:indent] || '  ',
    table_border_style: options[:table_border_style] || :simple
  }

  # Pre-process frontmatter
  content, fm_pairs, fm_vertical = Frontmatter.extract(markdown_text)

  # Pre-process inline math $...$ (kramdown needs a math-engine gem for this)
  math_color = AnsiCode.color(*MarkdownTheme[:math])
  content = content.gsub(/(?<!\$)\$(?!\$)(.+?)(?<!\$)\$(?!\$)/) do
    rendered = TerminalConverter::LatexConverter.convert(Regexp.last_match(1).strip)
    "#{math_color}#{rendered}#{AnsiCode.reset}"
  end

  fm_output = ""
  if fm_pairs && !fm_pairs.empty?
    if fm_vertical
      # Vertical frontmatter: one column per key-value pair
      fm_output = render_frontmatter_vertical(fm_pairs, converter_options)
    else
      fm_output = render_frontmatter_horizontal(fm_pairs, converter_options)
    end
  end

  kramdown_opts = {
    input: 'GFM',                 # GitHub Flavored Markdown
    syntax_highlighter: nil,      # 自行处理语法高亮
    hard_wrap: false,
    html_to_native: true,
    line_width: converter_options[:width]
  }.merge(options[:kramdown] || {})

  doc = Kramdown::Document.new(content, kramdown_opts)
  result, _warnings = TerminalConverter.convert(doc.root, converter_options)
  "#{fm_output}#{result}"
end

.render_frontmatter_horizontal(pairs, opts) ⇒ Object

Render frontmatter as a horizontal 2-row table (few pairs).



1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
# File 'lib/ruby_rich/markdown.rb', line 1348

def self.render_frontmatter_horizontal(pairs, opts)
  keys = pairs.map(&:first)
  vals = pairs.map(&:last)
  tbl = RubyRich::Table.new(
    headers: keys,
    border_style: opts[:table_border_style] || :simple
  )
  tbl.add_row(vals)
  "#{tbl.render}\n\n"
end

.render_frontmatter_vertical(pairs, opts) ⇒ Object

Render frontmatter as a vertical key-value table (many pairs).



1338
1339
1340
1341
1342
1343
1344
1345
# File 'lib/ruby_rich/markdown.rb', line 1338

def self.render_frontmatter_vertical(pairs, opts)
  tbl = RubyRich::Table.new(
    headers: %w[Key Value],
    border_style: opts[:table_border_style] || :simple
  )
  pairs.each { |k, v| tbl.add_row([k, v]) }
  "#{tbl.render}\n\n"
end

Instance Method Details

#render(markdown_text) ⇒ Object



1363
1364
1365
# File 'lib/ruby_rich/markdown.rb', line 1363

def render(markdown_text)
  self.class.render(markdown_text, @options)
end