Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
blessed-contrib
Advanced tools
Build dashboards (or any other application) using ascii/ansi art and javascript.
Build dashboards (or any other application) using ascii/ansi art and javascript.
Friendly to terminals, ssh and developers. Extends blessed with custom drawille and other widgets.
You should also check WOPR: a markup for creating terminal reports, presentations and infographics.
Contributors:
Yaron Naveh (@YaronNaveh) Chris (@xcezzz) Miguel Valadas (@mvaladas) Liran Tal (@lirantal)
Demo (full size):
Running the demo
git clone https://github.com/yaronn/blessed-contrib.git
cd blessed-contrib
npm install
node ./examples/dashboard.js
Works on Linux, OS X and Windows. For Windows follow the pre requisites.
npm install blessed blessed-contrib
You can use any of the default widgets of blessed (texts, lists and etc) or the widgets added in blessed-contrib (described below). A layout is optional but useful for dashboards. The widgets in blessed-contrib follow the same usage pattern:
var blessed = require('blessed')
, contrib = require('blessed-contrib')
, screen = blessed.screen()
, line = contrib.line(
{ style:
{ line: "yellow"
, text: "green"
, baseline: "black"}
, xLabelPadding: 3
, xPadding: 5
, label: 'Title'})
, data = {
x: ['t1', 't2', 't3', 't4'],
y: [5, 1, 7, 5]
}
screen.append(line) //must append before setting data
line.setData([data])
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
return process.exit(0);
});
screen.render()
See below for a complete list of widgets.
var line = contrib.line(
{ style:
{ line: "yellow"
, text: "green"
, baseline: "black"}
, xLabelPadding: 3
, xPadding: 5
, showLegend: true
, wholeNumbersOnly: false //true=do not show fraction in y axis
, label: 'Title'})
var series1 = {
title: 'apples',
x: ['t1', 't2', 't3', 't4'],
y: [5, 1, 7, 5]
}
var series2 = {
title: 'oranges',
x: ['t1', 't2', 't3', 't4'],
y: [2, 1, 4, 8]
}
screen.append(line) //must append before setting data
line.setData([series1, series2])
Examples: simple line chart, multiple lines, 256 colors
var bar = contrib.bar(
{ label: 'Server Utilization (%)'
, barWidth: 4
, barSpacing: 6
, xOffset: 0
, maxHeight: 9})
screen.append(bar) //must append before setting data
bar.setData(
{ titles: ['bar1', 'bar2']
, data: [5, 10]})
bar = contrib.stackedBar(
{ label: 'Server Utilization (%)'
, barWidth: 4
, barSpacing: 6
, xOffset: 0
//, maxValue: 15
, height: "40%"
, width: "50%"
, barBgColor: [ 'red', 'blue', 'green' ]})
screen.append(bar)
bar.setData(
{ barCategory: ['Q1', 'Q2', 'Q3', 'Q4']
, stackedCategory: ['US', 'EU', 'AP']
, data:
[ [ 7, 7, 5]
, [8, 2, 0]
, [0, 0, 0]
, [2, 3, 2] ]
})
var map = contrib.map({label: 'World Map'})
map.addMarker({"lon" : "-79.0000", "lat" : "37.5000", color: "red", char: "X" })
var gauge = contrib.gauge({label: 'Progress', stroke: 'green', fill: 'white'})
gauge.setPercent(25)
Either specify each stacked portion with a percent
and stroke
...
var gauge = contrib.gauge({label: 'Stacked '})
gauge.setStack([{percent: 30, stroke: 'green'}, {percent: 30, stroke: 'magenta'}, {percent: 40, stroke: 'cyan'}])
Or, you can just supply an array of numbers and random colors will be chosen.
var gauge = contrib.gauge({label: 'Stacked Progress'})
gauge.setStack([30,30,40])
var donut = contrib.donut({
label: 'Test',
radius: 8,
arcWidth: 3,
remainColor: 'black',
yPadding: 2,
data: [
{percent: 80, label: 'web1', color: 'green'}
]
});
Data passed in uses percent
and label
to draw the donut graph. Color is optional and defaults to green.
donut.setData([
{percent: 87, label: 'rcp','color': 'green'},
{percent: 43, label: 'rcp','color': 'cyan'},
]);
Updating the donut is as easy as passing in an array to setData
using the same array format as in the constructor. Pass in as many objects to the array of data as you want, they will automatically resize and try to fit. However, please note that you will still be restricted to actual screen space.
You can also hardcode a specific numeric into the donut's core display instead of the percentage by passing an percentAltNumber
property to the data, such as:
var donut = contrib.donut({
label: 'Test',
radius: 8,
arcWidth: 3,
remainColor: 'black',
yPadding: 2,
data: [
{percentAltNumber: 50, percent: 80, label: 'web1', color: 'green'}
]
});
See an example of this in one of the donuts settings on ./examples/donut.js
.
var lcd = contrib.lcd(
{ segmentWidth: 0.06 // how wide are the segments in % so 50% = 0.5
, segmentInterval: 0.11 // spacing between the segments in % so 50% = 0.550% = 0.5
, strokeWidth: 0.11 // spacing between the segments in % so 50% = 0.5
, elements: 4 // how many elements in the display. or how many characters can be displayed.
, display: 321 // what should be displayed before first call to setDisplay
, elementSpacing: 4 // spacing between each element
, elementPadding: 2 // how far away from the edges to put the elements
, color: 'white' // color for the segments
, label: 'Storage Remaining'})
lcd.setDisplay(23 + 'G'); // will display "23G"
lcd.setOptions({}) // adjust options at runtime
Please see the examples/lcd.js for an example. The example provides keybindings to adjust the segmentWidth
and segmentInterval
and strokeWidth
in real-time so that you can see how they manipulate the look and feel.
var log = contrib.log(
{ fg: "green"
, selectedFg: "green"
, label: 'Server Log'})
log.log("new log line")
(Also check the new blessed image implementation which has several benefits over this one.)
var pic = contrib.picture(
{ file: './flower.png'
, cols: 25
, onReady: ready})
function ready() {screen.render()}
note: only png images are supported
var spark = contrib.sparkline(
{ label: 'Throughput (bits/sec)'
, tags: true
, style: { fg: 'blue' }})
sparkline.setData(
[ 'Sparkline1', 'Sparkline2'],
[ [10, 20, 30, 20]
, [40, 10, 40, 50]])
var table = contrib.table(
{ keys: true
, fg: 'white'
, selectedFg: 'white'
, selectedBg: 'blue'
, interactive: true
, label: 'Active Processes'
, width: '30%'
, height: '30%'
, border: {type: "line", fg: "cyan"}
, columnSpacing: 10 //in chars
, columnWidth: [16, 12, 12] /*in chars*/ })
//allow control the table with the keyboard
table.focus()
table.setData(
{ headers: ['col1', 'col2', 'col3']
, data:
[ [1, 2, 3]
, [4, 5, 6] ]})
var tree = contrib.tree({fg: 'green'})
//allow control the table with the keyboard
tree.focus()
tree.on('select',function(node){
if (node.myCustomProperty){
console.log(node.myCustomProperty);
}
console.log(node.name);
}
// you can specify a name property at root level to display root
tree.setData(
{ extended: true
, children:
{
'Fruit':
{ children:
{ 'Banana': {}
, 'Apple': {}
, 'Cherry': {}
, 'Exotics': {
children:
{ 'Mango': {}
, 'Papaya': {}
, 'Kiwi': { name: 'Kiwi (not the bird!)', myCustomProperty: "hairy fruit" }
}}
, 'Pear': {}}}
, 'Vegetables':
{ children:
{ 'Peas': {}
, 'Lettuce': {}
, 'Pepper': {}}}}})
Every node is a hash and it can have custom properties that can be used in "select" event callback. However, there are several special keys :
string
{ name: 'Fruit'}
hash
or function(node){ return children }
node.childrenContent
and children
{'Fruit':{ name: 'Fruit', children:{ 'Banana': {}, 'Cherry': {}}}}
examples/explorer.js
hash
node.children
is a hash, node.children===node.childrenContent
node.children
is a function, it's used to store the node.children()
resultif(node.childrenContent)
in your node.children
function to generate children only onceboolean
treeInstance.options.extended
if the node extended
option is not set{'Fruit':{ name: 'Fruit', extended: true, children:{ 'Banana': {}, 'Cherry': {}}}}
var markdown = contrib.markdown()
markdown.setMarkdown('# Hello \n blessed-contrib renders markdown using `marked-terminal`')
You can use 256 colors (source):
function randomColor() {
return [Math.random() * 255,Math.random()*255, Math.random()*255]
}
line = contrib.line(
{
...
, style: { line: randomColor(), text: randomColor(), baseline: randomColor() }
})
A grid layout can auto position your elements in a grid layout. When using a grid, you should not create the widgets, rather specify to the grid which widget to create and with which params. Each widget can span multiple rows and columns.
var screen = blessed.screen()
var grid = new contrib.grid({rows: 12, cols: 12, screen: screen})
//grid.set(row, col, rowSpan, colSpan, obj, opts)
var map = grid.set(0, 0, 4, 4, contrib.map, {label: 'World Map'})
var box = grid.set(4, 4, 4, 4, blessed.box, {content: 'My Box'})
screen.render()
A carousel layout switches between different views based on time or keyboard activity. One use case is an office dashboard with rotating views:
var blessed = require('blessed')
, contrib = require('./')
, screen = blessed.screen()
function page1(screen) {
var map = contrib.map()
screen.append(map)
}
function page2(screen) {
var line = contrib.line(
{ width: 80
, height: 30
, left: 15
, top: 12
, xPadding: 5
, label: 'Title'
})
var data = [ { title: 'us-east',
x: ['t1', 't2', 't3', 't4'],
y: [0, 0.0695652173913043, 0.11304347826087, 2],
style: {
line: 'red'
}
}
]
screen.append(line)
line.setData(data)
}
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
return process.exit(0);
});
var carousel = new contrib.carousel( [page1, page2]
, { screen: screen
, interval: 3000 //how often to switch views (set 0 to never swicth automatically)
, controlKeys: true //should right and left keyboard arrows control view rotation
})
carousel.start()
Running the sample
git clone https://github.com/yaronn/blessed-contrib.git
cd blessed-contrib
npm install
node ./examples/dashboard.js
Installation (for a custom dashboard)
npm install blessed
npm install blessed-contrib
A simple dashboard
var blessed = require('blessed')
, contrib = require('blessed-contrib')
, screen = blessed.screen()
, grid = new contrib.grid({rows: 1, cols: 2, screen: screen})
var line = grid.set(0, 0, 1, 1, contrib.line,
{ style:
{ line: "yellow"
, text: "green"
, baseline: "black"}
, xLabelPadding: 3
, xPadding: 5
, label: 'Stocks'})
var map = grid.set(0, 1, 1, 1, contrib.map, {label: 'Servers Location'})
var lineData = {
x: ['t1', 't2', 't3', 't4'],
y: [5, 1, 7, 5]
}
line.setData([lineData])
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
return process.exit(0);
});
screen.render()
Rich dashboard
See source code
If you see questions marks or some (or all) missign characters try running with these env vars to fix encoding / terminal:
$> LANG=en_US.utf8 TERM=xterm-256color node your-code.js
This library is under the MIT License
FAQs
Build dashboards (or any other application) using ascii/ansi art and javascript.
The npm package blessed-contrib receives a total of 27,556 weekly downloads. As such, blessed-contrib popularity was classified as popular.
We found that blessed-contrib demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.