Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Create composable extensible styled text in both consoles and browsers.
Install it with NPM or add it to your package.json
:
$ npm install magicpen
Then:
var magicpen = require('magicpen');
var pen = magicpen();
pen.red('Hello').sp().green('world!');
console.log(pen.toString('ansi'));
Include magicpen.js
.
<script src="magicpen.js"></script>
this will expose the magicpen
function under the following namespace:
var magicpen = weknowhow.magicpen;
var pen = magicpen();
pen.red('Hello').sp().green('world!');
document.getElementById('output').innerHTML = pen.toString('html');
Include the library with RequireJS the following way:
require.config({
paths: {
magicpen: 'path/to/magicpen'
}
});
define(['magicpen'], function (magicpen) {
var pen = magicpen();
pen.red('Hello').sp().green('world!');
document.getElementById('output').innerHTML = pen.toString('html');
});
You create a new magicpen
instance by calling the magicpen
function. Then you can use methods on the instance to append content to
the output. Finally when you created the desired output you can
serialize it to plain text
, ansi
encoded text or html
.
Let's try to create our first magicpen
and serialize the output to
text to ansi
encoding:
var pen = magicpen();
pen.red('Hello').sp().green('world!');
console.log(pen.toString('ansi'));
The above snippet create a new magicpen
and writes Hello in red,
space and world! in green and prints the formatted output to the
console. This will produce the following output:
![Hello world!](images/Hello world - ansi.png)
Let's try to create the same output but format it as html:
var pen = magicpen();
pen.red('Hello').sp().green('world!');
document.getElementById('output').innerHTML = pen.toString('html');
You will get the following output it the browser:
![Hello world!](images/Hello world - html.png)
Creates a new instance of MagicPen with the given options.
Currently there is only two options: indentationWidth
which defaults
to 2 and format
.
Given magicpen a string is equivalent to specifying the format in the options object:
Specifying the format is useful in combination with the raw
method.
Example:
// Pen with indentation width 2
magicpen();
// Pen with indentation width 2 and in ansi format
magicpen('ansi');
// Pen with indentation width 4
magicpen({ indentationWidth: 4 });
Append the given content to the output with the styles specified in the style strings.
Text properties:
Foreground colors:
Background colors:
var pen = magicpen();
pen.text('Hello', 'red')
.text(' ')
.text('colorful', 'yellow', 'bold')
.text(' ')
.text('world', 'green', 'underline')
.text('!', 'bgYellow', 'blue');
console.log(pen.toString('ansi'));
![Hello colorful world](images/Hello colorful world.png)
Notice that special characters might get escaped by this method. The example below shows how special html characters is escaped by the html format.
var pen = magicpen();
pen.text('<strong>Hello world!</strong>');
expect(pen.toString('html'), 'to equal',
'<div style="font-family: monospace; white-space: nowrap">\n' +
' <div><strong>Hello world!</strong></div>\n' +
'</div>');
When you use hex colors in the terminal the colors will be approximated to the palette in use. The below images shows a limited color sample in html and in a terminal supporting 256 colors.
![Color sample html](images/Color sample - html.png)
![Color sample ansi-256](images/Color sample - ansi-256.png)
Returns the content of the pen in the specified format.
Accepted formats are text
, ansi
and html
.
It fails if the pen has another format set already.
If no format is specified, it will use the format of the pen or text
if the pen does not have a format set.
Starts the given number of new lines.
Example:
pen.text('Hello').nl()
.indentLines()
.indent().text('beautiful').nl()
.outdentLines()
.text('world');
expect(pen.toString(), 'to equal',
'Hello\n' +
' beautiful\n' +
'world');
Increments the indentation level.
Decrements the indentation level.
Appends the indentation to the output.
You can control the indentation size by setting indentationWidth
option when creating the pen.
var pen = magicpen({ indentationWidth: 4 });
Appends the content of the given pen to the end of this pen.
Example:
var pen = magicpen();
var otherPen = pen.clone().text('world!');
pen.text('Hello').sp().append(otherPen);
expect(pen.toString(), 'to equal', 'Hello world!');
var pen = magicpen();
pen.text('Hello').sp().append(function () {
this.text('world!');
});
expect(pen.toString(), 'to equal', 'Hello world!');
Appends the content of the given pen to the end of this pen in an inline block.
Example:
var pen = magicpen();
var otherPen = pen.clone()
.text(' // This is a').nl()
.text(' // multiline block');
pen.text('Text before block').block(otherPen);
expect(pen.toString(), 'to equal',
'Text before block // This is a\n' +
' // multiline block');
var pen = magicpen();
pen.text('Text before block').block(function () {
this.text(' // This is a').nl()
.text(' // multiline block');
});
expect(pen.toString(), 'to equal',
'Text before block // This is a\n' +
' // multiline block');
var pen = magicpen();
pen.red('Hello').block('text', ' // This is a\n // multiline comment');
expect(pen.toString(), 'to equal',
'Hello // This is a\n' +
' // multiline comment');
Amends the content to the end of the pen.
Example:
var pen = magicpen();
pen.block('text', 'This is a\n' +
'multiline block\n' +
'but you can still\n' +
'amend text to\n' +
'it');
pen.amend(pen.clone().text('!'));
expect(pen.toString(), 'to equal',
'This is a\n' +
'multiline block\n' +
'but you can still\n' +
'amend text to\n' +
'it!');
var pen = magicpen();
pen.block('text', 'This is a\n' +
'multiline block\n' +
'but you can still\n' +
'amend text to\n' +
'it');
pen.amend(function () {
this.text('!');
});
expect(pen.toString(), 'to equal',
'This is a\n' +
'multiline block\n' +
'but you can still\n' +
'amend text to\n' +
'it!');
var pen = magicpen();
pen.block('text', 'This is a\n' +
'multiline block\n' +
'but you can still\n' +
'amend text to\n' +
'it');
pen.amend('text', '!');
expect(pen.toString(), 'to equal',
'This is a\n' +
'multiline block\n' +
'but you can still\n' +
'amend text to\n' +
'it!');
Prepends each line of this pen with the content of the given pen.
Example:
var pen = magicpen();
var otherPen = pen.clone().text('> ');
pen.text('Line').nl()
.text('after line').nl()
.text('after line')
.prependLinesWith(otherPen);
expect(pen.toString(), 'to equal',
'> Line\n' +
'> after line\n' +
'> after line');
var pen = magicpen();
pen.text('Line').nl()
.text('after line').nl()
.text('after line')
.prependLinesWith(function () {
this.text('> ');
});
expect(pen.toString(), 'to equal',
'> Line\n' +
'> after line\n' +
'> after line');
var pen = magicpen();
pen.text('Line').nl()
.text('after line').nl()
.text('after line')
.prependLinesWith('grey', '> ');
expect(pen.toString(), 'to equal',
'> Line\n' +
'> after line\n' +
'> after line');
Returns the dimensions of the content of this pen.
Example:
var pen = magicpen();
pen.text('First line').nl()
.text('Second line');
expect(pen.size(), 'to equal', {
height: 2,
width: 11
});
Returns a clone of the current pen with an empty output buffer. This operation is very cheap, so don't hesitate to use it when it makes sense.
If a format is given, the pen cloned pen will have that format. This
is useful in combination with the raw
method. It will fail if the
format of the pen has already been set.
Defines a new style for the magicpen. The usage is best explained by an example:
var pen = magicpen();
pen.addStyle('rainbow', function (text, rainbowColors) {
rainbowColors = rainbowColors ||
['gray', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan'];
for (var i = 0; i < text.length; i += 1) {
var color = rainbowColors[i % rainbowColors.length];
this.text(text[i], color);
}
});
pen.rainbow('The unicorns are flying low today').nl();
.rainbow('The unicorns are flying low today', ['green', 'red', 'cyan']);
console.log(pen.toString('ansi'));
As you can see in the example above, a custom style can produce any kind of output using an instance of a magicpen.
Creates a new pen with the content of this pen where all text formatting is removed.
Example:
var pen = magicpen();
pen.red('Hello').sp().green('world');
console.log(pen.toString('ansi'));
console.log(pen.removeFormatting().toString('ansi'));
![Remove text formatting](images/Hello world - removeFormatting.png)
If you need something completely custom, you can specify the actual string content that will be used for each format. You can even output raw content to the serializer.
Notice that you must specify the format of the pen before using this method either at construction time or when cloning.
The format specific content can be of the following forms:
this
.If the format of the pen is not defined the fallback property will be used. The fallback method can be specified the following way:
this
.var pen = magicpen();
pen.addStyle('link', function (label, url) {
this.raw({
fallback: function () {
this.text(label).sp().text('(').blue(url).text(')');
},
text: function () {
this.text(label).sp().text('<').text(url).text('>');
},
html: {
height: 1,
width: label.length,
content: '<a href="' + url + '" alt="' + label + '">' + label + '</a>'
}
});
});
pen.clone('text').link('magicpen', 'https://github.com/sunesimonsen/magicpen');
pen.clone('ansi').link('magicpen', 'https://github.com/sunesimonsen/magicpen');
pen.clone('html').link('magicpen', 'https://github.com/sunesimonsen/magicpen');
This will be the output in text mode:
magicpen <https://github.com/sunesimonsen/magicpen\x1B[39m>
This will be the output in ansi mode:
magicpen (\x1B[34mhttps://github.com/sunesimonsen/magicpen\x1B[39m)
This will be the output in html mode:
<div style="font-family: monospace; white-space: nowrap">
<div><a href="https://github.com/sunesimonsen/magicpen" alt="magicpen">magicpen</a></div>
</div>
If you're already inside an alt method, you can add more alt output by passing the
content directly to the alt
method:
pen.alt({
html: function () {
this.text('Hello');
this.alt({
height: 100,
width: 100,
content: '<canvas id="whoa"></canvas>'
}).nl();
this.indentLines()
this.i().block(function () {
this.alt(function () {
this.text('it even works in blocks');
});
});
},
fallback: 'foo'
});
Returns true
if the output only contains a block.
expect(magicpen().block(function () {
this.text('foo');
}).isBlock(), 'to be true');
Returns true
if the output more than one line.
expect(magicpen().text('line 1').isMultiline(), 'to be false');
expect(magicpen().text('line 1\nline 2').isMultiline(), 'to be true');
MagicPen plugins are objects that adhere to the following interface:
{
name: <plugin name>,
dependencies: <an optional list of dependencies>,
installInto: <a function that will update the given magicpen instance>
}
The name of the plugin should be the same at the NPM package name.
A plugin can require a list of other plugins to be installed prior to installation of the plugin. If the dependency list is not fulfilled the installation will fail. The idea is that you manage your plugin versions using NPM. If you install a plugin that is already installed nothing will happen.
The installInto
function receives an instance of unexpected and uses
uses the addStyle
method to add new custom styles to the MagicPen
instance.
var pen = magicpen();
pen.installPlugin({
name: 'starPlugin',
installInto: function (pen) {
pen.addStyle('stars', function (content) {
this.text(String(content).replace(/./g, '*'));
});
}
);
pen.stars('secret');
expect(pen.toString(), 'to equal', '******');
MagicPen have support for theming text styles differently for each format. A theme is just a hash of aliases to build in text styles or aliases to other theme entries. You install the theme for one or more formats.
pen.installTheme({
keyword: 'yellow',
functionName: ['green', 'italic'],
primitive: '#FF8DFE',
number: 'primitive'
});
After installing the theme you get the following methods on the pen
keyword
, functionName
and number
. If you wish to install the
theme after writing to the pen, you need to use the text
method
instead: pen.text('this uses the keyword style', 'keyword')
Let's print some code with the pen:
pen.keyword('function').sp().functionName('fib').text(' {').nl()
.indentLines()
.i().keyword('var').text(' i=0, fibs = [').number(0).text(', ').number(1)
.text('];').nl()
.i().keyword('for').text(' (; i < n; i += ').number(1).text(') {').nl()
.indentLines()
.i().text('fibs.push(fibs[').number(0).text('] + fibs[').number(1)
.text(']);').nl()
.i().text('fibs.shift();').nl()
.outdentLines()
.i().text('}').nl()
.i().keyword('return').text(' fibs[').number(0).text('];').nl()
.outdentLines()
.text('}');
This will produce the following ansi output:
But these colors looks pretty lame on white background, which we usually use when outputting to the html format:
Let's tweak the html colors without touching the ansi colors:
pen.installTheme('html', {
keyword: 'bold',
functionName: ['#403298', 'italic', 'bold'],
primitive: '#80417F'
});
You can even extend the current theme:
pen.installTheme('html', {
functionName: ['#5B9832', 'bold']
});
The theme is applied at serialization time, so you can change the theme and serialize again with the theme applied without touching the content of the pen.
Alias for text(duplicate(' ', count))
.
Alias for text(content, 'bold')
.
Alias for text(content, 'dim')
.
Alias for text(content, 'italic')
.
Alias for text(content, 'underline')
.
Alias for text(content, 'inverse')
.
Alias for text(content, 'hidden')
.
Alias for text(content, 'strikeThrough')
.
Alias for text(content, 'black')
.
Alias for text(content, 'red')
.
Alias for text(content, 'green')
.
Alias for text(content, 'yellow')
.
Alias for text(content, 'blue')
.
Alias for text(content, 'magenta')
.
Alias for text(content, 'cyan')
.
Alias for text(content, 'white')
.
Alias for text(content, 'gray')
.
Alias for text(content, 'bgBlack')
.
Alias for text(content, 'bgRed')
.
Alias for text(content, 'bgGreen')
.
Alias for text(content, 'bgYellow')
.
Alias for text(content, 'bgBlue')
.
Alias for text(content, 'bgMagenta')
.
Alias for text(content, 'bgCyan')
.
Alias for text(content, 'bgWhite')
.
MIT, see the LICENSE
file for details.
FAQs
Styled output in both consoles and browsers
The npm package magicpen receives a total of 11,988 weekly downloads. As such, magicpen popularity was classified as popular.
We found that magicpen demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 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.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.