diff --git a/src/core/config/Categories.js b/src/core/config/Categories.js
index b2c404f..33ec4a9 100755
--- a/src/core/config/Categories.js
+++ b/src/core/config/Categories.js
@@ -67,6 +67,7 @@ const Categories = [
"Encode text",
"Decode text",
"Swap endianness",
+ "To Table",
]
},
{
diff --git a/src/core/config/OperationConfig.js b/src/core/config/OperationConfig.js
index bbe80a0..5d2ca47 100644
--- a/src/core/config/OperationConfig.js
+++ b/src/core/config/OperationConfig.js
@@ -37,6 +37,7 @@ import SeqUtils from "../operations/SeqUtils.js";
import Shellcode from "../operations/Shellcode.js";
import StrUtils from "../operations/StrUtils.js";
import Tidy from "../operations/Tidy.js";
+import ToTable from "../operations/ToTable.js";
import Unicode from "../operations/Unicode.js";
import URL_ from "../operations/URL.js";
@@ -613,6 +614,38 @@ const OperationConfig = {
}
]
},
+ "To Table": {
+ module: "Default",
+ description: "Renders data as a table. Data can be split on different characters and output as a HTML or ASCII table with optional header row.",
+ inputType: "string",
+ outputType: "html",
+ highlight: false,
+ highlightReverse: false,
+ manualBake: false,
+ args: [
+ {
+ name: "Select separator",
+ type: "populateOption",
+ value: ToTable.SEPARATORS,
+ target: 1
+ },
+ {
+ name: "Separator",
+ type: "string",
+ value: ","
+ },
+ {
+ name: "First row header?",
+ type: "boolean",
+ value: false
+ },
+ {
+ name: "Format",
+ type: "option",
+ value: ToTable.FORMATS
+ }
+ ]
+ },
"From Hex": {
module: "Default",
description: "Converts a hexadecimal byte string back into its raw value.
e.g. ce 93 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85 0a
becomes the UTF-8 encoded string Γειά σου
",
diff --git a/src/core/config/modules/Default.js b/src/core/config/modules/Default.js
index e5f070c..6b9f60f 100644
--- a/src/core/config/modules/Default.js
+++ b/src/core/config/modules/Default.js
@@ -27,6 +27,7 @@ import Rotate from "../../operations/Rotate.js";
import SeqUtils from "../../operations/SeqUtils.js";
import StrUtils from "../../operations/StrUtils.js";
import Tidy from "../../operations/Tidy.js";
+import ToTable from "../../operations/ToTable.js";
import Unicode from "../../operations/Unicode.js";
import UUID from "../../operations/UUID.js";
import XKCD from "../../operations/XKCD.js";
@@ -163,6 +164,7 @@ OpModules.Default = {
"Mean": Arithmetic.runMean,
"Median": Arithmetic.runMedian,
"Standard Deviation": Arithmetic.runStdDev,
+ "To Table": ToTable.runToTable,
"Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix,
"UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix,
"XKCD Random Number": XKCD.runRandomNumber,
diff --git a/src/core/operations/ToTable.js b/src/core/operations/ToTable.js
new file mode 100755
index 0000000..3422719
--- /dev/null
+++ b/src/core/operations/ToTable.js
@@ -0,0 +1,189 @@
+import Utils from "../Utils.js";
+
+/**
+ * ToTable operations.
+ *
+ * @author Mark Jones [github.com/justanothermark]
+ * @namespace
+ */
+ const ToTable = {
+ /**
+ * @constant
+ * @default
+ */
+ SEPARATORS: [
+ {name: "Comma", value:","},
+ {name: "Tab", value: escape("\t")},
+ {name: "Pipe", value: "|"},
+ {name: "Custom", value: ""}
+ ],
+
+ /**
+ * @constant
+ * @default
+ */
+ FORMATS: [
+ 'ASCII',
+ 'HTML'
+ ],
+
+ /**
+ * To Table operation.
+ *
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {html}
+ */
+ runToTable: function (input, args) {
+ let separator = args[1];
+ let firstRowHeader = args[2];
+ let format = args[3];
+ let tableData = [];
+
+ // If the separator contains any tabs, convert them to tab characters.
+ separator = separator.replace('\\t', '\t');
+
+ // Process the input into a nested array of elements.
+ let rows = input.split('\n');
+ rows.forEach(function(element) {
+ if (separator == '') {
+ tableData.push([element]);
+ }
+ else {
+ tableData.push(element.split(separator));
+ }
+ });
+
+ // Render the data in the requested format.
+ let output = '';
+ switch (format) {
+ case 'ASCII':
+ output = asciiOutput(tableData);
+ break;
+
+ default:
+ output = htmlOutput(tableData);
+ break;
+ }
+
+ return output;
+
+ /**
+ * Outputs an array of data as an ASCII table.
+ *
+ * @param {Array[]} tableData
+ * @returns {string}
+ */
+ function asciiOutput(tableData) {
+ const horizontalBorder = '-';
+ const verticalBorder = '|';
+ const crossBorder = '+';
+
+ let output = '';
+ let longestCells = [];
+
+ // Find longestCells value per column to pad cells equally.
+ tableData.forEach(function(row, index) {
+ row.forEach(function(cell, cellIndex) {
+ if (longestCells[cellIndex] == undefined || cell.length > longestCells[cellIndex]) {
+ longestCells[cellIndex] = cell.length;
+ }
+ });
+ });
+
+ // Calculate the complete row length. This is the length of the
+ // longest cell for each column plus 3 characters per cell
+ // (1 padding each side of the value and 1 for the cell border)
+ // plus 1 for the final cell border.
+ let rowLength = (longestCells.length * 3) + 1;
+ longestCells.forEach(function(celllongestCells) {
+ rowLength += celllongestCells;
+ });
+
+ // Add the top border of the table to the output.
+ output += outputHorizontalBorder(longestCells);
+
+ // If the first row is a header, remove the row from the data and
+ // add it to the output with another horizontal border.
+ if (firstRowHeader) {
+ let row = tableData.shift();
+ output += outputRow(row, longestCells);
+ output += outputHorizontalBorder(longestCells);
+ }
+
+ // Add the rest of the table rows.
+ tableData.forEach(function(row, index) {
+ output += outputRow(row, longestCells);
+ });
+
+ // Close the table with a final horizontal border.
+ output += outputHorizontalBorder(longestCells);
+
+ return output;
+
+ /**
+ * Outputs a row of correctly padded cells.
+ */
+ function outputRow(row, longestCells) {
+ let rowOutput = verticalBorder;
+ row.forEach(function(cell, index) {
+ rowOutput += ' ' + cell + ' '.repeat(longestCells[index] - cell.length) + ' ' + verticalBorder;
+ });
+ rowOutput += '\n';
+ return rowOutput;
+ }
+
+ /**
+ * Outputs a horizontal border with a different character where
+ * the horizontal border meets a vertical border.
+ */
+ function outputHorizontalBorder(longestCells) {
+ let rowOutput = crossBorder;
+ longestCells.forEach(function(cellLength) {
+ rowOutput += horizontalBorder.repeat(cellLength + 2) + crossBorder;
+ });
+ rowOutput += '\n';
+ return rowOutput;
+ }
+ }
+
+ /**
+ * Outputs a table of data as a HTML table.
+ */
+ function htmlOutput(tableData) {
+ // Start the HTML output with suitable classes for styling.
+ let output = "
cells. + if (firstRowHeader) { + let row = tableData.shift(); + output += ""; + output += outputRow(row, 'th'); + output += ""; + } + + // Output the rest of the rows in the | . + output += ""; + tableData.forEach(function(row, index) { + output += outputRow(row, 'td'); + }); + + // Close the body and table elements. + output += "
---|