Module: Rubino::Documents::Table

Defined in:
lib/rubino/documents/table.rb

Overview

The ONE Markdown table emitter shared by the csv and xlsx converters (the reuse seam the plan calls for). Takes an array of rows (each an array of cell values) and emits a GFM pipe table: the first row is the header, a ‘|—|` separator follows, then the body. Pipes and newlines inside cells are escaped so a cell value can’t break the table grid. Rows are capped so a runaway spreadsheet can’t emit a million-line table into context.

Constant Summary collapse

MAX_ROWS =

Hard cap on emitted body rows; over the cap we truncate and note it.

1000

Class Method Summary collapse

Class Method Details

.cell(value) ⇒ Object

Escapes a cell so pipes/newlines can’t break the table. nil -> “”.



54
55
56
57
58
59
60
# File 'lib/rubino/documents/table.rb', line 54

def cell(value)
  value.to_s
       .gsub("\\", "\\\\\\\\")
       .gsub("|", "\\|")
       .gsub(/\r\n?|\n/, "<br>")
       .strip
end

.emit(rows, max_rows: MAX_ROWS) ⇒ Object

rows: Array<Array> – first row is the header. Returns a GFM table String, or “” when there are no rows.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/rubino/documents/table.rb', line 19

def emit(rows, max_rows: MAX_ROWS)
  rows = Array(rows).compact
  return "" if rows.empty?

  width = rows.map { |r| Array(r).length }.max
  return "" if width.nil? || width.zero?

  header = pad(rows.first, width)
  body   = rows.drop(1)
  truncated = body.length > max_rows
  body = body.first(max_rows) if truncated

  lines = []
  lines << row_line(header)
  lines << separator(width)
  body.each { |r| lines << row_line(pad(r, width)) }
  out = lines.join("\n")
  out += "\n\n_(#{rows.length - 1 - max_rows} more rows truncated)_" if truncated
  out
end

.pad(row, width) ⇒ Object



40
41
42
43
# File 'lib/rubino/documents/table.rb', line 40

def pad(row, width)
  cells = Array(row).map { |c| cell(c) }
  cells.fill("", cells.length...width)
end

.row_line(cells) ⇒ Object



45
46
47
# File 'lib/rubino/documents/table.rb', line 45

def row_line(cells)
  "| #{cells.join(" | ")} |"
end

.separator(width) ⇒ Object



49
50
51
# File 'lib/rubino/documents/table.rb', line 49

def separator(width)
  "|#{(["---"] * width).join("|")}|"
end