table is array of rows, where row is array of cells, cell is array of spans
function formatTable(table, links, notes) {
  var widths = [];
  var rows = table.map(function (row) {
    var cells = row.map(function (cell) {
      return formatSpans(cell, links, notes);
    });
    cells.forEach(function (cell, index) {
      widths[index] = Math.max(cell.length, widths[index] || 5);
      widths[index] = Math.min(widths[index], 50);
    });
    return cells.join(' & ');
  });

  var totalWidth = widths.reduce(function sum(val, width) { return val + width; }, 0);
  totalWidth = Math.max(totalWidth, 100);
  widths = widths.map(function (width) {
    var relativeWidth = width / totalWidth;
    return 'p{' + relativeWidth + '\\textwidth}';
  }).join(' | ');

  var str =
    '\\begin{longtable}{ | ' + widths + ' |}\n' +
    '\\hline\n' +
    rows.join(' \\\\\n\\hline\n') +
    ' \\\\\n' +
    '\\hline\n' +
    '\\end{longtable}';
  return str;
}