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.



1352
1353
1354
# File 'lib/ruby_rich/markdown.rb', line 1352

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 格式的终端输出



1290
1291
1292
1293
1294
1295
1296
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
# File 'lib/ruby_rich/markdown.rb', line 1290

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).



1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
# File 'lib/ruby_rich/markdown.rb', line 1341

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).



1331
1332
1333
1334
1335
1336
1337
1338
# File 'lib/ruby_rich/markdown.rb', line 1331

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



1356
1357
1358
# File 'lib/ruby_rich/markdown.rb', line 1356

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