Class: MarkdownTables

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

Class Method Summary collapse

Class Method Details

.make_table(labels, data, align: '', is_rows: false) ⇒ Object

Generate a Markdown table. labels and data are one and two-dimensional arrays, respectively. All input must have a to_s method. Pass align: ‘l’ for left alignment or ‘r’ for right alignment. Anything else will result in cells being centered. Pass an array of align values to specify alignment per column. If is_rows is true, then each sub-array of data represents a row. Conversely, if is_rows is false, each sub-array of data represents a column. Empty cells can be given with nil or an empty string.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/markdown-tables.rb', line 12

def self.make_table(labels, data, align: '', is_rows: false)
  validate(labels, data, align, is_rows)

  # Deep copy the arguments so we don't mutate the originals.
  labels = Marshal.load(Marshal.dump(labels))
  data = Marshal.load(Marshal.dump(data))

  # Remove any breaking Markdown characters.
  labels.map! {|label| sanitize(label)}
  data.map! {|datum| datum.map {|cell| sanitize(cell)}}

  # Convert align to something that other methods won't need to validate.
  align.class == String && align = [align] * labels.length
  align.map! {|a| a =~ /[lr]/i ? a.downcase : 'c'}

  # Generate the column labels and alignment line.
  header_line = labels.join('|')
  alignment_line = parse_alignment(align, labels.length)

  # Pad the data arrays so that it can be transposed if necessary.
  max_len = data.map(&:length).max
  data.map! {|datum| fill(datum, max_len)}

  # Generate the table rows.
  rows = (is_rows ? data : data.transpose).map {|row| row.join('|')}

  return [header_line, alignment_line, rows.join("\n")].join("\n")
end

.plain_text(md_table) ⇒ Object

Convert a Markdown table into human-readable form.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/markdown-tables.rb', line 42

def self.plain_text(md_table)
  md_table !~ // && raise('Invalid input')

  # Split the table into lines to get the labels, rows, and alignments.
  lines = md_table.split("\n")
  alignments = lines[1].split('|')
  # labels or rows might have some empty values but alignments
  # is guaranteed to be of the right width.
  table_width = alignments.length
  # '|||'.split('|') == [], so we need to manually add trailing empty cells.
  # Leading empty cells are taken care of automatically.
  labels = fill(lines[0].split('|'), table_width)
  rows = lines[2..-1].map {|line| fill(line.split('|'), table_width)}

  # Get the width for each column.
  cols = rows.transpose
  widths = cols.each_index.map {|i| column_width(cols[i].push(labels[i]))}

  # Align the labels and cells.
  labels = labels.each_index.map { |i|
    aligned_cell(unsanitize(labels[i]), widths[i], alignments[i])
  }
  rows.map! { |row|
    row.each_index.map { |i|
      aligned_cell(unsanitize(row[i]), widths[i], alignments[i])
    }
  }

  border = "\n|" + widths.map {|w| '=' * w}.join('|') + "|\n"
  return (
    border + [
      '|' + labels.join('|') + '|',
      rows.map {|row| '|' + row.join('|') + '|'}.join(border.tr('=', '-'))
    ].join(border) + border
  ).strip

end