Socket
Socket
Sign inDemoInstall

column-layout

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

column-layout - npm Package Compare versions

Comparing version 0.0.0 to 1.0.0-alpha.1

example/five-columns-width.json

37

bin/cli.js
#!/usr/bin/env node
"use strict";
var columns = require("../");
var columnLayout = require("../");
var tr = require("transform-tools");
var cliArgs = require("command-line-args");
var pkg = require("../package");
var cli = cliArgs([
{ name: "help", type: Boolean, alias: "h" },
{ name: "width", type: Array, alias: "w", description: "specify a list of column widths in the format '<column>:<width>', for example:\n$ cat <json data> | column-layout --width \"column 1: 10\" \"column 2: 30\"" }
]);
var options = cli.parse();
if (options.help){
console.error(cli.getUsage({
title: "column-layout",
header: pkg.description,
forms: [
"$ cat <json data> | column-format <options>"
]
}));
process.exit(0);
}
var columns = [];
if (options.width){
options.width.forEach(function(columnWidth){
var split = columnWidth.split(":").map(function(item){
return item.trim();
});
if (split[0] && split[1]){
columns.push({ name: split[0], width: Number(split[1]) });
}
})
}
process.stdin
.pipe(tr.collectJson({ through: function(json){
return columns(json, { viewWidth: process.stdout.columns });
var clOptions = { viewWidth: process.stdout.columns };
if (columns.length) clOptions.columns = columns;
return columnLayout(json, clOptions);
}}))
.pipe(process.stdout);

19

example/usage.json
{
"options": {
"columns": [
{ "name": "line", "nowrap": true },
{ "name": "option", "nowrap": true },
{ "name": "description", "width": 20 }
{ "name": "description" }
]
},
"data": [
{ "line": "Example App" },
{ "line": "This is an example app, yeah?" },
{ "line": "" },
{ "line": "Usage" },
{ "line": "$ example one two" },
{ "line": "" },
"\u001b[1mExample App\u001b[0m",
"This is an example app, yeah?",
"",
"\u001b[1mUsage\u001b[0m",
"$ example one two",
"",
{ "option": "-t, --template", "description": "blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah"},
{ "option": "-v, --verbose", "description": "yeah yeah yeah"},
{ "option": "-s, --something", "description": "bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang bang"},
{ "line": "" },
{ "line": "This is the footer" }
"",
"This is the footer"
]
}

@@ -6,15 +6,37 @@ "use strict";

var o = require("object-tools");
var t = require("typical");
/**
@module column-layout
*/
module.exports = columnLayout;
/**
Returns JSON data formatted in columns.
@param {array} - input data
@param [options] {object} - optional settings
@param [options.viewWidth] {number} - maximum width of layout
@param [options.columns] {module:column-layout~columnOption} - array of column options
@returns {string}
@alias module:column-layout
@example
> columnFormat = require("column-format")
> jsonData = [{
col1: "Some text you wish to read in column layout",
col2: "And some more text in column two. "
}]
> columnFormat(jsonData, { viewWidth: 30 })
' Some text you And some more \n wish to read text in \n in column column two. \n layout \n'
*/
function columnLayout(data, options){
/* option to display all unique field names */
var cols = ColumnLayout(data, options);
return cols.toString();
}
options = o.extend({
viewWidth: 100,
padding: {
left: " ",
right: " "
}
}, options);
function ColumnLayout(data, options){
if (!(this instanceof ColumnLayout)) return new ColumnLayout(data, options);
var self = this;
options = options || {};
/* split input into data and options */
if (!Array.isArray(data)){

@@ -28,89 +50,45 @@ if (data.options && data.data){

}
this.options = options;
this.data = data;
if (!options.columns) options.columns = [];
if (options.columns){
options.columns = options.columns.map(function(columnOptions){
if (columnOptions.nowrap) {
columnOptions.width = getColumnWidth(self.data, columnOptions.name);
}
return columnOptions;
});
} else {
options.columns = getUniquePropertyNames(this.data).map(function(column){
return { name: column, width: getColumnWidth(self.data, column) };
});
var totalWidth = total(options.columns, "width");
var widthDiff = totalWidth + (options.columns.length * 2) - options.viewWidth;
// console.log(totalWidth, options.viewWidth, widthDiff);
if (widthDiff > 0){
a.sortBy(options.columns, "width");
var widestColumn = a(options.columns).last();
widestColumn.width -= widthDiff;
}
// console.log(options.columns);
}
/* get rows which require column layout */
var rows = a(data).where(function(row){
return t.isObject(row);
}).val();
this.dataSplit = this.data.map(function(row){
/* create a cellLines array for each column */
var cells = Object.keys(row).map(function(col){
var cellValue = String(typeof row[col] === "undefined" || row[col] === null ? "" : row[col]);
var columnOptions = a(self.options.columns).findWhere({ name: col });
cellValue = wrap(cellValue, { width: columnOptions.width, trim: true });
var cellLines = cellValue.split(/\n/).map(function(cellLine){
return s.padRight(cellLine, columnOptions.width + 2);
});
return cellLines;
});
/* fill empty cell lines */
if (cells.length > 1){
var mostLines = getMostLines(cells);
cells = cells.map(function(cellLines, index){
var columnOptions = a(self.options.columns).findWhere({ name: Object.keys(row)[index] });
for (var i = 0; i < mostLines; i++){
if (typeof cellLines[i] === "undefined") cellLines.push(s.repeat(" ", columnOptions.width + 2));
}
return cellLines;
});
/* if no column options supplied, create them.. */
var uniquePropertyNames = getUniquePropertyNames(rows);
var columnsWithoutOptions = a(uniquePropertyNames).without(a.pluck(options.columns, "name")).val();
columnsWithoutOptions.forEach(function(columnName){
options.columns.push(createColumnOption(columnName));
});
/* for 'nowrap' columns, or columns with no specific width, set the width to the content width */
options.columns.forEach(function(columnOption){
if (typeof columnOption.width === "undefined" || columnOption.nowrap){
columnOption = autosizeColumn(rows, columnOption, options);
}
return cells;
return columnOption;
});
}
ColumnLayout.prototype.toString = function(){
return this.dataSplit.reduce(function(output, row){
var totalContentWidth = sum(options.columns, "width");
var widthDiff = totalContentWidth - options.viewWidth;
/* make adjustments if the total width is above the available width */
if (widthDiff > 0){
autoSizeColumnWidths(options, rows)
}
var dataSplit = data.map(renderRow.bind(null, options));
return dataSplit.reduce(function(output, row){
output += mergeArrays(row).join("\n") + "\n";
return output;
}, "");
};
ColumnLayout.prototype.getVal = function(col, val){
return s.padRight(val || "", this.getColumnOptionsWidth(col) + 2);
};
ColumnLayout.prototype.getColumnOptionsWidth = function(col){
var column = a.findWhere(this.options.columns, { name: col });
return (column && column.width) || null;
};
ColumnLayout.prototype.getLongestLine = function(col){
return this.data.reduce(function(longestLine, row){
}, 0);
};
function getColumnWidth(data, columnName){
return data.reduce(function(columnWidth, row){
var width = String(row[columnName]).length;
if (width > columnWidth) columnWidth = width;
return columnWidth;
}, 0);
}
function getMostLines(cells){
return cells.reduce(function(mostLines, cell){
if (cell.length > mostLines) mostLines = cell.length;
return mostLines;
function getLongestItem(array){
return array.reduce(function(longest, item){
if (!Array.isArray(item)) item = String(item);
if (item.length > longest) longest = item.length;
return longest;
}, 0);

@@ -132,15 +110,132 @@ }

function getUniquePropertyNames(recordset){
return recordset.reduce(function(propertyNames, record){
Object.keys(record).forEach(function(key){
if (!a.contains(propertyNames, key)) propertyNames.push(key);
function getUniquePropertyNames(rows){
return rows.reduce(function(keys, row){
Object.keys(row).forEach(function(key){
if (!a.contains(keys, key)) keys.push(key);
});
return propertyNames;
return keys;
}, []);
}
function total(recordset, columnName){
return recordset.reduce(function(total, row){
return total + Number(row[columnName]);
/**
@param {array} - input array
@param [propertyName] {string} - if the input array is a recordset, sum values from this property
@private
*/
function sum(array, property){
return array.reduce(function(total, item){
return total + Number(property ? item[property] : item);
}, 0);
}
function getWrappableColumns(rows, columnOptions){
var wrappableColumns = columnsContaining(rows, /\s+/);
return wrappableColumns.filter(function(wrappableCol){
var columnOption = getColumnOption(columnOptions, wrappableCol);
return !(columnOption.nowrap || !columnOption._auto);
});
}
function getUnWrappableColumns(rows, columnOptions){
return a(columnOptions)
.pluck("name")
.without(getWrappableColumns(rows, columnOptions))
.val();
}
function getCellLines(options, row, column){
var cellValue = row[column];
var width = getColumnOption(options.columns, column).width;
cellValue = String(typeof cellValue === "undefined" || cellValue === null ? "" : cellValue);
cellValue = wrap(cellValue, { width: width - getPaddingWidth(options), trim: true, indent: "" });
var cellLines = cellValue.split(/\n/).map(padCell.bind(null, options, width));
return cellLines;
}
/**
converts a row (object) into an array of "cellLines" arrays, with an equal number of lines, each line padded to the specified column width
@private
*/
function renderRow(options, row){
if (typeof row === "string"){
return [ [ row ] ];
} else {
/* create a cellLines array for each column */
var cellLinesRow = Object.keys(row).map(getCellLines.bind(null, options, row));
/* ensure each cellLines array has the same amount of lines */
if (cellLinesRow.length > 1){
var mostLines = getLongestItem(cellLinesRow);
cellLinesRow = cellLinesRow.map(function(cellLines, index){
var width = getColumnOption(options.columns, Object.keys(row)[index]).width;
for (var i = 0; i < mostLines; i++){
if (typeof cellLines[i] === "undefined") cellLines.push(padCell(options, width, ""));
}
return cellLines;
});
}
return cellLinesRow;
}
}
function padCell(options, width, value){
return options.padding.left + s.padRight(value, width - getPaddingWidth(options)) + options.padding.right;
}
function autoSizeColumnWidths(options, data){
var wrappableColumns = getWrappableColumns(data, options.columns);
var unWrappableColumns = getUnWrappableColumns(data, options.columns);
var totalWidthOfUnwrappableColumns = sum(
a(options.columns).where(unWrappableColumns.map(function(colName){
return { name: colName };
})).val(),
"width"
);
var remainingWidth = options.viewWidth - totalWidthOfUnwrappableColumns;
var reductionShare = Math.floor(remainingWidth / wrappableColumns.length);
wrappableColumns.forEach(function(columnName){
getColumnOption(options.columns, columnName).width = reductionShare;
});
}
function autosizeColumn(rows, columnOption, options){
var columnValues = a.pluck(rows, columnOption.name);
columnOption.width = getLongestItem(columnValues) + getPaddingWidth(options);
columnOption._auto = true;
return columnOption;
}
function getPaddingWidth(options){
return options.padding.left.length + options.padding.right.length;
}
function createColumnOption(name){
return { name: name };
}
function getColumnOption(columnOptions, columnName){
var columnOption = a(columnOptions).findWhere({ name: columnName });
if (!columnName) throw Error("Could not find column options for: " + columnName);
return columnOption;
}
function columnsContaining(rows, test){
return rows.reduce(function(columns, row){
o.each(row, function(val, key){
if (test.test(String(val).trim())){
if (!a(columns).contains(key)) columns.push(key);
}
});
return columns;
}, []);
}
/**
@typedef module:column-layout~columnOption
@property [width] {number} - column width
@property [nowrap] {boolean} - disable wrapping for this column
@property [padding] {object} - padding options
@property [padding.left] {string} - a string to pad the left of each cell (default: `" "`)
@property [padding.right] {string} - a string to pad the right of each cell (default: `" "`)
*/
{
"name": "column-layout",
"author": "Lloyd Brookes <75pound@gmail.com>",
"version": "0.0.0",
"description": "column-layout",
"version": "1.0.0-alpha.1",
"description": "Pretty-print JSON data in columns.",
"repository": "https://github.com/75lb/column-layout.git",
"license": "MIT",
"main": "./lib/column-layout.js",
"bin": {
"cols": "bin/cli.js"
},
"keywords": [],
"bin": "bin/cli.js",
"keywords": [
"wrap",
"terminal",
"data",
"columns",
"format",
"json",
"command line"
],
"engines": {

@@ -26,4 +32,9 @@ "node": ">=0.10.0"

"transform-tools": "^0.1.1",
"word-wrap": "^1.0.3"
"typical": "^2.2.0",
"word-wrap": "^1.0.3",
"command-line-args": "~0.5.9"
},
"devDependencies": {
"jsdoc-to-markdown": "^1.1.1"
}
}
[![view on npm](http://img.shields.io/npm/v/column-layout.svg)](https://www.npmjs.org/package/column-layout)
[![npm module downloads per month](http://img.shields.io/npm/dm/column-layout.svg)](https://www.npmjs.org/package/column-layout)
[![Build Status](https://travis-ci.org/75lb/column-layout.svg?branch=master)](https://travis-ci.org/75lb/column-layout)
[![Dependency Status](https://david-dm.org/75lb/column-layout.svg)](https://david-dm.org/75lb/column-layout)
#column-layout
# column-layout
Pretty-print JSON data in columns.
## Synopsis
Say you have some data:
```json
[
{
"column 1": "The Kingdom of Scotland was a state in north-west Europe traditionally said to have been founded in 843, which joined with the Kingdom of England to form a unified Kingdom of Great Britain in 1707. Its territories expanded and shrank, but it came to occupy the northern third of the island of Great Britain, sharing a land border to the south with the Kingdom of England. It suffered many invasions by the English, but under Robert I it fought a successful war of independence and remained a distinct state in the late Middle Ages. In 1603, James VI of Scotland became King of England, joining Scotland with England in a personal union. In 1707, the two kingdoms were united to form the Kingdom of Great Britain under the terms of the Acts of Union. ",
"column 2": "Operation Barbarossa (German: Unternehmen Barbarossa) was the code name for Nazi Germany's invasion of the Soviet Union during World War II, which began on 22 June 1941. Over the course of the operation, about four million soldiers of the Axis powers invaded Soviet Russia along a 2,900 kilometer front, the largest invasion force in the history of warfare. In addition to troops, the Germans employed some 600,000 motor vehicles and between 600–700,000 horses. The operation was driven by Adolf Hitler's ideological desire to conquer the Soviet territories as outlined in his 1925 manifesto Mein Kampf ('My Struggle'). It marked the beginning of the rapid escalation of the war, both geographically and in the formation of the Allied coalition."
}
]
```
pipe it through `column-layout`:
```sh
$ cat example/two-columns.json | column-layout
```
to get this:
```
The Kingdom of Scotland was a state in Operation Barbarossa (German:
north-west Europe traditionally said Unternehmen Barbarossa) was the code
to have been founded in 843, which name for Nazi Germany's invasion of
joined with the Kingdom of England to the Soviet Union during World War II,
form a unified Kingdom of Great which began on 22 June 1941. Over the
Britain in 1707. Its territories course of the operation, about four
expanded and shrank, but it came to million soldiers of the Axis powers
occupy the northern third of the invaded Soviet Russia along a 2,900
island of Great Britain, sharing a kilometer front, the largest invasion
land border to the south with the force in the history of warfare. In
Kingdom of England. It suffered many addition to troops, the Germans
invasions by the English, but under employed some 600,000 motor vehicles
Robert I it fought a successful war of and between 600–700,000 horses. The
independence and remained a distinct operation was driven by Adolf Hitler's
state in the late Middle Ages. In ideological desire to conquer the
1603, James VI of Scotland became King Soviet territories as outlined in his
of England, joining Scotland with 1925 manifesto Mein Kampf ('My
England in a personal union. In 1707, Struggle'). It marked the beginning of
the two kingdoms were united to form the rapid escalation of the war, both
the Kingdom of Great Britain under the geographically and in the formation of
terms of the Acts of Union. the Allied coalition.
```
Columns containing wrappable data are auto-sized by default to fit the available space. You can set specific widths using `--width`
```sh
$ cat example/two-columns.json | column-layout --width "column 2: 45"
```
```
The Kingdom of Scotland was a Operation Barbarossa (German: Unternehmen
state in north-west Europe Barbarossa) was the code name for Nazi
traditionally said to have been Germany's invasion of the Soviet Union
founded in 843, which joined with during World War II, which began on 22 June
the Kingdom of England to form a 1941. Over the course of the operation,
unified Kingdom of Great Britain about four million soldiers of the Axis
in 1707. Its territories expanded powers invaded Soviet Russia along a 2,900
and shrank, but it came to occupy kilometer front, the largest invasion force
the northern third of the island in the history of warfare. In addition to
of Great Britain, sharing a land troops, the Germans employed some 600,000
border to the south with the motor vehicles and between 600–700,000
Kingdom of England. It suffered horses. The operation was driven by Adolf
many invasions by the English, Hitler's ideological desire to conquer the
but under Robert I it fought a Soviet territories as outlined in his 1925
successful war of independence manifesto Mein Kampf ('My Struggle'). It
and remained a distinct state in marked the beginning of the rapid
the late Middle Ages. In 1603, escalation of the war, both geographically
James VI of Scotland became King and in the formation of the Allied
of England, joining Scotland with coalition.
England in a personal union. In
1707, the two kingdoms were
united to form the Kingdom of
Great Britain under the terms of
the Acts of Union.
```
Plain strings in the input data are passed straight through to the output - useful for injecting lines around the column layout:
```sh
$ cat example/usage.json | column-layout
```
<pre><code><strong>Example App</strong>
This is an example app, yeah?
<strong>Usage</strong>
$ example one two
-t, --template blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah
-v, --verbose yeah yeah yeah
-s, --something bang bang bang bang bang bang bang bang bang bang bang bang
bang bang bang bang bang bang bang bang bang bang bang bang
bang bang bang bang bang bang
This is the footer
</code></pre>
## More Examples
Read the latest npm issues:
```sh
$ curl -s https://api.github.com/repos/npm/npm/issues \
| array-tools pick number title updated_at user.login comments \
| column-layout
```
```
8738 install: Run the "install" 2015-06-27T22:19:33Z iarna
lifecycle in the toplevel module
8737 npm install (-g) (everything) 2015-06-27T22:15:52Z DerekFoulk 2
completely broken after upgrade
to 2.12.0 [Windows]
8736 node-gyp not executed on npm@3 2015-06-27T22:19:19Z piranna 2
8735 Graceful fs 4 2015-06-27T21:12:57Z isaacs
8734 npm start failed dont get why its 2015-06-27T21:12:36Z kashikhan1
happened error windows_nt
6.3.9600 error on npm start
8733 npm install error "elliptic curve 2015-06-27T21:07:15Z MF-Bra
routines"
8732 No clue what do 2015-06-27T20:05:26Z worldlynx
8731 npm does not work on IPv6 2015-06-27T17:33:10Z hobarrera
8730 Pass module version on preversion 2015-06-27T17:11:57Z zanona
and postversion scripts.
8729 problem installing cordova on 2015-06-27T14:28:35Z axtens
Windows
8728 npm error 2015-06-27T14:20:42Z hyguyz
8727 npm install error 2015-06-27T13:40:56Z wfgenius
8726 Why can't I install the npm? 2015-06-27T17:37:51Z PleasantPro 2
etc.
etc.
```
## API Reference
* [column-layout](#module_column-layout)
* [columnLayout(data, [options])](#exp_module_column-layout--columnLayout) ⇒ <code>string</code> ⏏
* [~columnOption](#module_column-layout--columnLayout..columnOption)
<a name="exp_module_column-layout--columnLayout"></a>
### columnLayout(data, [options]) ⇒ <code>string</code> ⏏
Returns JSON data formatted in columns.
**Kind**: Exported function
| Param | Type | Description |
| --- | --- | --- |
| data | <code>array</code> | input data |
| [options] | <code>object</code> | optional settings |
| [options.viewWidth] | <code>number</code> | maximum width of layout |
| [options.columns] | <code>[columnOption](#module_column-layout--columnLayout..columnOption)</code> | array of column options |
**Example**
```js
> columnFormat = require("column-format")
> jsonData = [{
col1: "Some text you wish to read in column layout",
col2: "And some more text in column two. "
}]
> columnFormat(jsonData, { viewWidth: 30 })
' Some text you And some more \n wish to read text in \n in column column two. \n layout \n'
```
<a name="module_column-layout--columnLayout..columnOption"></a>
#### columnLayout~columnOption
**Kind**: inner typedef of <code>[columnLayout](#exp_module_column-layout--columnLayout)</code>
**Properties**
| Name | Type | Description |
| --- | --- | --- |
| width | <code>number</code> | column width |
| nowrap | <code>boolean</code> | disable wrapping for this column |
| padding | <code>object</code> | padding options |
| padding.left | <code>string</code> | a string to pad the left of each cell (default: `" "`) |
| padding.right | <code>string</code> | a string to pad the right of each cell (default: `" "`) |
* * *
&copy; 2015 Lloyd Brookes \<75pound@gmail.com\>. Documented by [jsdoc-to-markdown](https://github.com/jsdoc2md/jsdoc-to-markdown).

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc