ToTable.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /**
  2. * ToTable operations.
  3. *
  4. * @author Mark Jones [github.com/justanothermark]
  5. * @copyright Crown Copyright 2018
  6. * @license Apache-2.0
  7. *
  8. * @namespace
  9. */
  10. import Utils from "../Utils.js";
  11. const ToTable = {
  12. /**
  13. * @constant
  14. * @default
  15. */
  16. FORMATS: [
  17. "ASCII",
  18. "HTML"
  19. ],
  20. /**
  21. * To Table operation.
  22. *
  23. * @param {string} input
  24. * @param {Object[]} args
  25. * @returns {html}
  26. */
  27. runToTable: function (input, args) {
  28. const [cellDelims, rowDelims, firstRowHeader, format] = args;
  29. // Process the input into a nested array of elements.
  30. const tableData = Utils.parseCSV(input, cellDelims.split(""), rowDelims.split(""));
  31. if (!tableData.length) return "";
  32. // Render the data in the requested format.
  33. switch (format) {
  34. case "ASCII":
  35. return asciiOutput(tableData);
  36. case "HTML":
  37. default:
  38. return htmlOutput(tableData);
  39. }
  40. /**
  41. * Outputs an array of data as an ASCII table.
  42. *
  43. * @param {string[][]} tableData
  44. * @returns {string}
  45. */
  46. function asciiOutput(tableData) {
  47. const horizontalBorder = "-";
  48. const verticalBorder = "|";
  49. const crossBorder = "+";
  50. let output = "";
  51. let longestCells = [];
  52. // Find longestCells value per column to pad cells equally.
  53. tableData.forEach(function(row, index) {
  54. row.forEach(function(cell, cellIndex) {
  55. if (longestCells[cellIndex] === undefined || cell.length > longestCells[cellIndex]) {
  56. longestCells[cellIndex] = cell.length;
  57. }
  58. });
  59. });
  60. // Add the top border of the table to the output.
  61. output += outputHorizontalBorder(longestCells);
  62. // If the first row is a header, remove the row from the data and
  63. // add it to the output with another horizontal border.
  64. if (firstRowHeader) {
  65. let row = tableData.shift();
  66. output += outputRow(row, longestCells);
  67. output += outputHorizontalBorder(longestCells);
  68. }
  69. // Add the rest of the table rows.
  70. tableData.forEach(function(row, index) {
  71. output += outputRow(row, longestCells);
  72. });
  73. // Close the table with a final horizontal border.
  74. output += outputHorizontalBorder(longestCells);
  75. return output;
  76. /**
  77. * Outputs a row of correctly padded cells.
  78. */
  79. function outputRow(row, longestCells) {
  80. let rowOutput = verticalBorder;
  81. row.forEach(function(cell, index) {
  82. rowOutput += " " + cell + " ".repeat(longestCells[index] - cell.length) + " " + verticalBorder;
  83. });
  84. rowOutput += "\n";
  85. return rowOutput;
  86. }
  87. /**
  88. * Outputs a horizontal border with a different character where
  89. * the horizontal border meets a vertical border.
  90. */
  91. function outputHorizontalBorder(longestCells) {
  92. let rowOutput = crossBorder;
  93. longestCells.forEach(function(cellLength) {
  94. rowOutput += horizontalBorder.repeat(cellLength + 2) + crossBorder;
  95. });
  96. rowOutput += "\n";
  97. return rowOutput;
  98. }
  99. }
  100. /**
  101. * Outputs a table of data as a HTML table.
  102. *
  103. * @param {string[][]} tableData
  104. * @returns {string}
  105. */
  106. function htmlOutput(tableData) {
  107. // Start the HTML output with suitable classes for styling.
  108. let output = "<table class='table table-hover table-condensed table-bordered table-nonfluid'>";
  109. // If the first row is a header then put it in <thead> with <th> cells.
  110. if (firstRowHeader) {
  111. let row = tableData.shift();
  112. output += "<thead>";
  113. output += outputRow(row, "th");
  114. output += "</thead>";
  115. }
  116. // Output the rest of the rows in the <tbody>.
  117. output += "<tbody>";
  118. tableData.forEach(function(row, index) {
  119. output += outputRow(row, "td");
  120. });
  121. // Close the body and table elements.
  122. output += "</tbody></table>";
  123. return output;
  124. /**
  125. * Outputs a table row.
  126. *
  127. * @param {string[]} row
  128. * @param {string} cellType
  129. */
  130. function outputRow(row, cellType) {
  131. let output = "<tr>";
  132. row.forEach(function(cell) {
  133. output += "<" + cellType + ">" + cell + "</" + cellType + ">";
  134. });
  135. output += "</tr>";
  136. return output;
  137. }
  138. }
  139. }
  140. };
  141. export default ToTable;