Skip to content

Commit b06ff3d

Browse files
committed
chalk compatibility, client enhancements
1 parent a36a726 commit b06ff3d

File tree

11 files changed

+506
-116
lines changed

11 files changed

+506
-116
lines changed

README.md

+82-97
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,69 @@
1-
ascii-art.js
2-
===========
1+
_ _ _
2+
(_)(_) | |
3+
__ _ ___ ___ _ _ ______ __ _ _ __ | |_
4+
/ _` |/ __| / __|| || ||______| / _` || '__|| __|
5+
| (_| |\__ \| (__ | || | | (_| || | | |_
6+
\__,_||___/ \___||_||_| \__,_||_| \__|
7+
8+
###ascii-art.js
9+
10+
Images, fonts and terminal styles in Node.js & the browser. 100% JS.
11+
12+
It features support for [Images](docs/Images.md), [Styles](docs/Images.md) and [Figlet Fonts](docs/Figlet.md) as well as handling multi-line joining automatically.
13+
14+
In the beginning there was [colors.js](https://github.com/Marak/colors.js) but in the fine tradition of vendors calling out a problem they have the solution to, [chalk](https://github.com/yeoman/yo/issues/68) was introduced. In that same vein, I offer `ascii-art` to [solve](docs/Multiline.md) [many](docs/Figlet.md) [problems](docs/Images.md) which chalk ignores.
15+
16+
Why would I use this instead of X?
17+
----------------------------------
18+
- **zero dependencies** - while the CL utility and test have dependencies, we will never call out to a module for what is supposed to be this lib's core competancy.
19+
- **color profiles** support - other libraries assume you are running x11
20+
- **no prototype manipulation** - Nobody is actually forcing String.prototype on anyone, but that doesn't stop it being a hot topic. In addition, we don't use `__proto__` under the hood and pretending we aren't doing dynamic prototype manipulation (zing!).
21+
- handles the ugly [intersection of **multiline text and ansi codes**](doc/Multiline.md) for you.
22+
- runs in the **browser and Node.js** (CommonJS, AMD, globals or webpack)
23+
- **JS + Canvas** Ascii image generation utilities in node don't actually touch any pixels, but usually call out to a binary, we do 100% of our transform in JS, which allows us plug into averaging, distance and other logic dynamically, in powerful ways.
24+
- **Expressive API** is a buzzword for chaining from days of yore, but the other guys are excited about having one and we have one too.
25+
- It **works like a package manager** for figlet fonts.
26+
- The other libraries out there do too little and focus on logging above other domains.
27+
- **Actively maintained** If we don't update the code we'll tweak a code of conduct or something... maybe just re-up with self congratulatory pull requests, just to keep kicking that can. We might even add badges if we get saucy.
28+
- **Supports your existing API** We allow you to use the colors.js/chalk API *or* our own (where we reserve chaining for more useful activities).
29+
- **Loads nothing that isn't used** (Images, Fonts, Image Logic, etc.)
30+
- It's **awesome** and that thing you're holding is looking played out.
331

4-
Draw images, render fonts and manipulate terminal styles in Node.js & the browser. 100% JS.
5-
6-
Figlet fonts
7-
------------
8-
A slight mod of [Figlet.js](https://github.com/scottgonzalez/figlet-js) which I hope will make it to NPM in pure js form someday, rather than requiring a command line dependency.
9-
10-
Figlet fonts are an ASCII art font standard, widely used for terminal output.
11-
12-
It looks something like this:
13-
14-
______ _
15-
| _ \ | |
16-
| | | | ___ _ __ ___ ___ | |
17-
| | | | / _ \| '_ ` _ \ / _ \ | |
18-
| |/ / | __/| | | | | || (_) ||_|
19-
|___/ \___||_| |_| |_| \___/ (_)
20-
21-
To set the directory of the fonts:
22-
23-
art.Figlet.fontPath = 'Fonts';
24-
25-
Then to render some text:
26-
27-
art.font('my text', 'Doom', function(rendered){
28-
//do stuff here
29-
});
30-
31-
Styles
32-
------
33-
ANSI terminals allow us to output style which format the text in the terminal. In order to do this you just need to:
34-
35-
art.style('my text', 'red+underline');
36-
37-
1. **colors**
38-
Foreground colors for characters are: black, red, green, yellow, blue, magenta, cyan, white and in some terminal environments: bright_black, bright_red, bright_green, bright_yellow, bright_blue, bright_magenta, bright_cyan, bright_white (These generally default to their non-bright variants on systems without them)
39-
40-
2. **background colors**
41-
Background terminal colors available are: black_bg, red_bg, green_bg, yellow_bg, blue_bg, magenta_bg, cyan_bg, white_bg
42-
43-
3. **styles**
44-
To style the text you may use: bold, italic, underline, framed, encircled, overline, blink, inverse
45-
46-
4. **controls**
47-
Control styles are: off, hidden
48-
49-
Images
50-
------
51-
Images require [canvas]() but only optionally upon first reference of `art.Image()` the constructor takes an options argument
52-
53-
- alphabet : requires one of `variant1`, `variant2`, `variant3`, `variant4`, `ultra-wide`, `wide`, `hatching`, `bits`, `binary`, `greyscale`, `blocks`
54-
- filepath(*required*) : the path of the image
55-
- width : # of terminal columns
56-
- height : # of terminal rows
57-
- distance : a function which takes in 6 args (2x rgb) and returns a measure of distance between these two colors
58-
59-
So for example, say we want to generate a copy of a metropolis poster:
32+
33+
On the Command Line
34+
------------------
6035

61-
![Image Output](http://patternweaver.com/Github/Ascii/docs/metropolis.jpg)
36+
npm install -g ascii-art
37+
38+
Look at a list of fonts from the maintainers of Figlet:
6239

63-
You just need to do something like this:
40+
ascii-art list all
41+
42+
Preview your font in a browser:
6443

65-
var image = new art.Image({
66-
filepath: '~/Images/metropolis.jpg',
67-
alphabet:'variant4'
68-
});
69-
image.write(function(err, rendered){
70-
console.log(rendered);
71-
})
44+
ascii-art preview doom
45+
46+
Now, install a figlet font
7247

73-
![Image Output](http://patternweaver.com/Github/Ascii/docs/metropolis.png)
48+
ascii-art install doom
49+
50+
Render some text
7451

75-
Binary
76-
------
77-
You can run ascii-art as a commandline converter:
52+
ascii-art text -s green -F doom "some text"
53+
54+
or render an image (use `npm run sample` to generate and view a gallery)
7855

7956
ascii-art image -f path/to/my/file.jpg
80-
81-
82-
Chaining
83-
--------
84-
85-
The font method also allows you to optionally pass styles and supports chaining, so if I want something a little more complex I could do something like this:
57+
58+
In your Code
59+
------------
60+
The font method also allows you to optionally pass styles and supports chaining, so if I want two strings rendered together:
8661

8762
art.font('Prompt', 'Basic', 'red').font('v1', 'Doom', 'magenta', function(rendered){
8863
console.log(rendered);
8964
});
90-
91-
and that will look like this (in color, of course) and it will totally respect the multiline chars and add in ansi codes per line, so things look how you'd expect:
92-
93-
d8888b. d8888b. .d88b. .88b d88. d8888b. d888888b __
94-
88 `8D 88 `8D .8P Y8. 88'YbdP`88 88 `8D `~~88~~' / |
95-
88oodD' 88oobY' 88 88 88 88 88 88oodD' 88 __ __`| |
96-
88~~~ 88`8b 88 88 88 88 88 88~~~ 88 \ \ / / | |
97-
88 88 `88. `8b d8' 88 88 88 88 88 \ V / _| |_
98-
88 88 YD `Y88P' YP YP YP 88 YP \_/ \___/
9965

100-
Of course to match the `.font()` chain, there is also an `image()` chain, you can blend them like so:
66+
There is also an `image()` call in the chain, that requires `canvas` in Node.js and shims in the browser's `Canvas` object (but only when image is used, so that dependency is optional):
10167

10268
art.image({
10369
width : 40,
@@ -107,9 +73,32 @@ Of course to match the `.font()` chain, there is also an `image()` chain, you ca
10773
console.log(ascii);
10874
});
10975

110-
Which produces something like:
76+
Which produces (from [this](Images/initech.png) and [this](Fonts/doom.flf)):
77+
78+
![Mixed Content Example](http://patternweaver.com/Github/Ascii/docs/initech.png)
79+
80+
81+
| **Color Table** | `color` | bright_`color` | `color`_bg|
82+
| -----------------------------|---------------|-----------------|-----------|
83+
| black | <div style="background-color:#000000;height:10px"><div> | <div style="background-color:#808080;height:10px"><div> | <div style="background-color:#000000;height:10px"><div> |
84+
| red | <div style="background-color:#800000;height:10px"><div> | <div style="background-color:#ff0000;height:10px"><div> | <div style="background-color:#800000;height:10px"><div> |
85+
| green | <div style="background-color:#008000;height:10px"><div> | <div style="background-color:#00ff00;height:10px"><div> | <div style="background-color:#008000;height:10px"><div> |
86+
| yellow | <div style="background-color:#808000;height:10px"><div> | <div style="background-color:#ffff00;height:10px"><div> | <div style="background-color:#808000;height:10px"><div> |
87+
| blue | <div style="background-color:#000080;height:10px"><div> | <div style="background-color:#0000ff;height:10px"><div> | <div style="background-color:#000080;height:10px"><div> |
88+
| cyan | <div style="background-color:#008080;height:10px"><div> | <div style="background-color:#00ffff;height:10px"><div> | <div style="background-color:#008080;height:10px"><div> |
89+
| magenta | <div style="background-color:#800080;height:10px"><div> | <div style="background-color:#ff00ff;height:10px"><div> | <div style="background-color:#800080;height:10px"><div> |
90+
| white | <div style="background-color:#c0c0c0;height:10px"><div> | <div style="background-color:#ffffff;height:10px"><div> | <div style="background-color:#c0c0c0;height:10px"><div> |
91+
92+
Styles are: *italic*, **bold**, <span style="text-decoration: underline">underline</span>, <span style="text-decoration: underline overline">|framed|</span>, <span style="text-decoration: underline overline">|encircled|</span>, <span style="text-decoration: overline">overline</span>, <span style="text-decoration: blink">blink</span> and <span style="display:inline-block; background-color:#777777; color: white">&nbsp;inverse&nbsp;</span>.
93+
94+
For example: if I wanted underlined blue text on a white background, my style would be `underlined+blue+white_bg`. Check out the detailed [style docs](docs/Styles.md) for more information.
95+
11196

112-
![Mixed Content Example](http://patternweaver.com/Github/Ascii/docs/initech.png);
97+
Compatibility
98+
-------------
99+
If you're a [chalk](https://www.npmjs.com/package/chalk) user, just use `var chalk = require('ascii-art/kaolin');` in place of your existing `chalk` references (Much of color.js, too... since chalk is a subset of colors.js). No migration needed, keep using the wacky syntax you are used to(In this mode, refer to their docs, not mine).
100+
101+
I may support the other [colors](https://www.npmjs.com/package/colors) stuff (extras & themes) eventually, but it's currently a low priority.
113102

114103
Testing
115104
-------
@@ -121,15 +110,11 @@ which runs the test suite directly. In order to test it in Chrome try:
121110

122111
npm run browser-test
123112

124-
Please make sure to run the test suite before submitting a patch. Thanks!
125-
126-
Sample
127-
------
128-
To view a sample of graphics try:
113+
In order to run the chalk test, use:
129114

130-
npm run sample
131-
132-
Hope that helps, please report any rough edges!
115+
npm run chalk-test
116+
117+
Please make sure to run the tests before submitting a patch and report any rough edges. Thanks!
133118

134119
Enjoy,
135120

ascii-art.js

+8-5
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,12 @@
5050
alpha : false,
5151
errorMode : 'console',
5252
};
53-
AsciiArt.ansiCodes = function(str, color) {
53+
AsciiArt.ansiCodes = function(str, color, forceOff) {
5454
if(!color) return str;
5555
if(!this.codes){
5656
this.codes = {
5757
"off" : '\033[0m',
58+
"reset" : '\033[0m',
5859
"bold" : '\033[1m',
5960
"italic" : '\033[3m',
6061
"underline" : '\033[4m',
@@ -71,7 +72,8 @@
7172
"blue" : '\033[34m',
7273
"magenta" : '\033[35m',
7374
"cyan" : '\033[36m',
74-
"white" : '\033[37m',
75+
"white" : '\033[37m',
76+
"gray" : '\033[90m',
7577
"bright_black": '\033[90m',
7678
"bright_red" : '\033[91m',
7779
"bright_green": '\033[92m',
@@ -95,7 +97,8 @@
9597
for(var i=0, attr; attr = color_attrs[i]; i++) {
9698
ansi_str += this.codes[attr];
9799
}
98-
ansi_str += str + this.codes["off"];
100+
ansi_str += str;
101+
if(forceOff) ansi_str += this.codes["off"];
99102
return ansi_str;
100103
};
101104

@@ -188,7 +191,7 @@
188191
linesOne.forEach(function(line, index){
189192
if(index >= diff){
190193
if(style){
191-
linesOne[index] = linesOne[index]+AsciiArt.ansiCodes(linesTwo[index-diff], style);
194+
linesOne[index] = linesOne[index]+AsciiArt.ansiCodes(linesTwo[index-diff], style, true);
192195
}else{
193196
linesOne[index] = linesOne[index]+linesTwo[index-diff];
194197
}
@@ -259,7 +262,7 @@
259262
return chain.font(str, fontName, style);
260263
}else{
261264
return AsciiArt.Figlet.write(str, fontName, function(text){
262-
if(style) text = AsciiArt.ansiCodes(text, style);
265+
if(style) text = AsciiArt.ansiCodes(text, style, true);
263266
callback(text);
264267
});
265268
}

bin/ascii-art

+94-9
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,28 @@ var argv;
33
var yargs = require('yargs');
44
var fs = require('fs');
55
var art = require('../ascii-art');
6-
yargs.usage('Usage: $0 <command> [options]')
6+
yargs.usage('Usage: $0 <command> [options] <target>')
77
yargs.command('image', 'convert an image to ascii')
8-
.demand(1)
9-
.example('$0 image -f foo.jpg ', 'count the lines in the given file')
10-
.demand('f')
11-
.alias('f', 'file')
12-
.nargs('f', 1)
13-
.describe('f', 'Load a file')
8+
.command('text', 'add styles and/or font rendering to text')
9+
.demand(2)
10+
.example('$0 install Font.flf ', 'install a figlet font')
11+
.example('$0 image foo.jpg ', 'output foo.jpg as inline ascii text with ansi colors')
12+
.example('$0 text -F Doom "Some Titles"', 'outputs "Some Titles" in the Doom font')
13+
.example('$0 text -s red+underline "Some Titles"', 'outputs "Some Titles" with a red and underlined terminal style')
14+
.example('$0 text -F Doom "Some Titles"', 'outputs "Some Titles" in the Doom font')
15+
.example('$0 list all', 'show all fonts available at figlet.org')
16+
.example('$0 preview weird', 'visit the prieview page for weird.flf at figlet.org')
17+
.example('$0 install weird', 'install weird.flf into the local "/Fonts" directory')
18+
.example('$0 install weird -g', 'install weird.flf into the currently executing ascii-art instance')
19+
.alias('s', 'style')
20+
.nargs('s', 1)
21+
.describe('s', 'render a ansi style onto a string')
22+
.alias('F', 'font')
23+
.nargs('F', 1)
24+
.describe('F', 'render the output in the specified font')
25+
.alias('g', 'global')
26+
.nargs('g', 0)
27+
.describe('g', 'install the font globally')
1428
.alias('o', 'output')
1529
.nargs('o', 1)
1630
.describe('o', 'Save to a file')
@@ -23,11 +37,13 @@ yargs.command('image', 'convert an image to ascii')
2337
.alias('h', 'help')
2438
.epilog('©2016 - Abbey Hawk Sparrow');
2539
argv = yargs.argv;
26-
var action = argv._.pop();
40+
var action = argv._.shift();
41+
var target = argv._.pop();
42+
var ftp;
2743
switch(action){
2844
case 'image':
2945
var options = {
30-
filepath: argv.f
46+
filepath: target
3147
};
3248
if(argv.a) options.alphabet = argv.a;
3349
var image = new art.Image(options);
@@ -39,4 +55,73 @@ switch(action){
3955
}
4056
})
4157
break;
58+
case 'text':
59+
var output = function(result){ console.log(result) };
60+
if(argv.F){
61+
if(argv.s) art.font(target, argv.F, argv.s, output);
62+
else art.font(target, argv.F, output);
63+
}else{
64+
console.log(art.style(target, argv.s||'', true));
65+
}
66+
break;
67+
case 'list':
68+
var JSFtp = ftp || (ftp = require('jsftp'));
69+
var client = new JSFtp({
70+
host: "ftp.figlet.org"
71+
});
72+
var jobs=2;
73+
var results = [];
74+
client.ls("pub/figlet/fonts/ours", function(err, res) {
75+
if(!err) results = results.concat(res.map(function(item){
76+
return "ours/"+item.name
77+
}));
78+
client.ls("pub/figlet/fonts/contributed", function(err, res) {
79+
if(!err) results = results.concat(res.map(function(item){
80+
return "contributed/"+item.name
81+
}));
82+
client.raw.quit(function(err, data) {
83+
if (err) return console.error(err);
84+
var names = results.map(function(path){
85+
return path.split('/').pop().split('.').shift();
86+
})
87+
console.log(names);
88+
});
89+
});
90+
});
91+
break;
92+
case 'preview':
93+
var exec = require('child_process').exec;
94+
exec('open "http://www.figlet.org/fontdb_example.cgi?font='+target.toLowerCase()+'.flf"')
95+
break;
96+
//http://www.figlet.org/fontdb_example.cgi?font=hollywood.flf
97+
case 'install':
98+
//*
99+
var JSFtp = ftp || (ftp = require('jsftp'));
100+
var ftp = new JSFtp({
101+
host: "ftp.figlet.org"
102+
});
103+
var subdir = 'contributed'
104+
var url = 'pub/figlet/fonts/'+subdir+'/'+target.toLowerCase()+'.flf';
105+
ftp.get(url, function(err, socket) {
106+
if (err) return;
107+
var str = '';
108+
socket.on("data", function(d) { str += d.toString(); })
109+
socket.on("close", function(err) {
110+
if (err){
111+
console.error('There was an error retrieving the font '+target);
112+
}else{
113+
var dir = argv.g?process.cwd()+'/Fonts/':__dirname+'/../Fonts/';
114+
fs.writeFile(dir+target.toLowerCase()+'.flf', str, function(err){
115+
ftp.raw.quit(function(err, data) {
116+
if (err) return console.error(err);
117+
console.log(target+' written');
118+
});
119+
});
120+
}
121+
122+
});
123+
socket.resume();
124+
}); //*/
125+
break;
126+
default : throw new Error('unknown action: '+action);
42127
}

0 commit comments

Comments
 (0)