Skip to content

Commit c67eac1

Browse files
committed
Merge branch 'dev'
2 parents 5660ad9 + 34df74f commit c67eac1

File tree

5 files changed

+90
-24
lines changed

5 files changed

+90
-24
lines changed

README.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,38 @@ console.log(coolString);
6060
const gradient = require('gradient-string');
6161

6262
// Use the rainbow gradient
63-
gradient.rainbow('I love gradient-strings!')
63+
console.log(gradient.rainbow('I love gradient-strings!'))
6464
```
6565

6666
### Available built-in gradients
67+
6768
[![Built-in gradients](http://bit.ly/2uFygrL)](http://bit.ly/2ufX07r)
6869

70+
## Multi line gradients
71+
72+
In some cases, you may want to apply the same horizontal gradient on each line of a long text (or a piece of ASCII art).
73+
74+
You can use the `multiline()` method of a gradient to ensure that the colors are vertically aligned.
75+
76+
```javascript
77+
const gradient = require('gradient-string');
78+
79+
// Use the same gradient on every line
80+
let duck = gradient('orange', 'yellow').multiline([
81+
" __",
82+
"<(o )___",
83+
" ( ._> /",
84+
" `---'",
85+
].join('\n'));
86+
console.log(duck);
87+
88+
// Works with aliases
89+
gradient.atlas.multiline('Multi line\nstring');
90+
91+
// Works with advanced options
92+
gradient('cyan', 'pink').multiline('Multi line\nstring', {interpolation: 'hsv'});
93+
```
94+
6995
## Advanced gradients
7096

7197
<details>

examples/demo.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@ const log = console.log;
55
const str = ' Lorem ipsum dolor sit amet, consectetur adipiscing elit';
66
const title = Buffer.from('DQogICAgICAgICAgICAgICAgICAgICAgXyBfICAgICAgICAgICAgXyAgICAgICAgICAgIF8gICAgICAgIF8gICAgICAgICAgICAgDQogICBfXyBfIF8gX18gX18gXyAgX198IChfKSBfX18gXyBfXyB8IHxfICAgICAgX19ffCB8XyBfIF9fKF8pXyBfXyAgIF9fIF8gDQogIC8gX2AgfCAnX18vIF9gIHwvIF9gIHwgfC8gXyBcICdfIFx8IF9ffF9fX18vIF9ffCBfX3wgJ19ffCB8ICdfIFwgLyBfYCB8DQogfCAoX3wgfCB8IHwgKF98IHwgKF98IHwgfCAgX18vIHwgfCB8IHx8X19fX19cX18gXCB8X3wgfCAgfCB8IHwgfCB8IChffCB8DQogIFxfXywgfF98ICBcX18sX3xcX18sX3xffFxfX198X3wgfF98XF9ffCAgICB8X19fL1xfX3xffCAgfF98X3wgfF98XF9fLCB8DQogIHxfX18vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfF9fXy8gDQo=', 'base64').toString();
77

8-
for (const l of title.split('\n')) {
9-
log(gradient.pastel(l.replace(/\s/g, 'i')).replace(/i/g, ' '));
10-
}
11-
12-
log('');
8+
log(gradient.pastel.multiline(title) + '\n');
139

1410
for (const t of ['atlas', 'pastel', 'morning', 'cristal', 'rainbow']) {
1511
log(gradient[t](str) + '\n');

index.js

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,42 @@ const forbiddenChars = /\s/g;
77

88
function InitGradient() {
99
const grad = tinygradient.apply(this, arguments);
10-
return (str, opts) => applyGradient(str ? str.toString() : '', grad, opts);
10+
const ret = (str, opts) => applyGradient(str ? str.toString() : '', grad, opts);
11+
ret.multiline = (str, opts) => multilineGradient(str ? str.toString() : '', grad, opts);
12+
return ret;
1113
}
1214

15+
const getColors = (gradient, options, count) => options.interpolation.toLowerCase() === 'hsv' ?
16+
gradient.hsv(count, options.hsvSpin.toLowerCase()) : gradient.rgb(count);
17+
1318
function applyGradient(str, gradient, opts) {
1419
const options = validateOptions(opts);
1520
const colorsCount = Math.max(str.replace(forbiddenChars, '').length, gradient.stops.length);
16-
const colors = options.interpolation.toLowerCase() === 'hsv' ? gradient.hsv(colorsCount, options.hsvSpin.toLowerCase()) : gradient.rgb(colorsCount);
21+
const colors = getColors(gradient, options, colorsCount);
1722
let result = '';
1823
for (const s of str) {
1924
result += s.match(forbiddenChars) ? s : chalk.hex(colors.shift().toHex())(s);
2025
}
2126
return result;
2227
}
2328

29+
function multilineGradient(str, gradient, opts) {
30+
const options = validateOptions(opts);
31+
const lines = str.split('\n');
32+
const maxLength = Math.max(gradient.stops.length, ...(lines.map(l => l.length)));
33+
const colors = getColors(gradient, options, maxLength);
34+
const results = [];
35+
for (const line of lines) {
36+
const lineColors = colors.slice(0);
37+
let lineResult = '';
38+
for (const l of line) {
39+
lineResult += chalk.hex(lineColors.shift().toHex())(l);
40+
}
41+
results.push(lineResult);
42+
}
43+
return results.join('\n');
44+
}
45+
2446
function validateOptions(opts) {
2547
const options = Object.assign({interpolation: 'rgb', hsvSpin: 'short'}, opts);
2648
if (opts !== undefined && typeof opts !== 'object') {
@@ -37,18 +59,24 @@ function validateOptions(opts) {
3759
return options;
3860
}
3961

40-
module.exports = InitGradient;
62+
const aliases = {
63+
atlas: {colors: ['#feac5e', '#c779d0', '#4bc0c8'], options: {}},
64+
cristal: {colors: ['#bdfff3', '#4ac29a'], options: {}},
65+
teen: {colors: ['#77a1d3', '#79cbca', '#e684ae'], options: {}},
66+
mind: {colors: ['#473b7b', '#3584a7', '#30d2be'], options: {}},
67+
morning: {colors: ['#ff5f6d', '#ffc371'], options: {interpolation: 'hsv'}},
68+
vice: {colors: ['#5ee7df', '#b490ca'], options: {interpolation: 'hsv'}},
69+
passion: {colors: ['#f43b47', '#453a94'], options: {}},
70+
fruit: {colors: ['#ff4e50', '#f9d423'], options: {}},
71+
instagram: {colors: ['#833ab4', '#fd1d1d', '#fcb045'], options: {}},
72+
retro: {colors: ['#3f51b1', '#5a55ae', '#7b5fac', '#8f6aae', '#a86aa4', '#cc6b8e', '#f18271', '#f3a469', '#f7c978'], options: {}},
73+
summer: {colors: ['#fdbb2d', '#22c1c3'], options: {}},
74+
rainbow: {colors: ['#ff0000', '#ff0100'], options: {interpolation: 'hsv', hsvSpin: 'long'}},
75+
pastel: {colors: ['#74ebd5', '#74ecd5'], options: {interpolation: 'hsv', hsvSpin: 'long'}}
76+
};
4177

42-
module.exports.atlas = str => new InitGradient('#feac5e', '#c779d0', '#4bc0c8')(str);
43-
module.exports.cristal = str => new InitGradient('#bdfff3', '#4ac29a')(str);
44-
module.exports.teen = str => new InitGradient('#77a1d3', '#79cbca', '#e684ae')(str);
45-
module.exports.mind = str => new InitGradient('#473b7b', '#3584a7', '#30d2be')(str);
46-
module.exports.morning = str => new InitGradient('#ff5f6d', '#ffc371')(str, {interpolation: 'hsv'});
47-
module.exports.vice = str => new InitGradient('#5ee7df', '#b490ca')(str, {interpolation: 'hsv'});
48-
module.exports.passion = str => new InitGradient('#f43b47', '#453a94')(str);
49-
module.exports.fruit = str => new InitGradient('#ff4e50', '#f9d423')(str);
50-
module.exports.instagram = str => new InitGradient('#833ab4', '#fd1d1d', '#fcb045')(str);
51-
module.exports.retro = str => new InitGradient('#3f51b1', '#5a55ae', '#7b5fac', '#8f6aae', '#a86aa4', '#cc6b8e', '#f18271', '#f3a469', '#f7c978')(str);
52-
module.exports.summer = str => new InitGradient('#fdbb2d', '#22c1c3')(str);
53-
module.exports.rainbow = str => new InitGradient('#ff0000', '#ff0100')(str, {interpolation: 'hsv', hsvSpin: 'long'});
54-
module.exports.pastel = str => new InitGradient('#74ebd5', '#74ecd5')(str, {interpolation: 'hsv', hsvSpin: 'long'});
78+
module.exports = InitGradient;
79+
for (const a in aliases) { // eslint-disable-line guard-for-in
80+
module.exports[a] = str => new InitGradient(aliases[a].colors)(str, aliases[a].options);
81+
module.exports[a].multiline = str => new InitGradient(aliases[a].colors).multiline(str, aliases[a].options);
82+
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"name": "gradient-string",
33
"description": "Beautiful gradients in terminal stdout",
4-
"version": "0.1.2",
4+
"version": "1.0.0",
55
"author": "Boris K",
66
"bugs": "https://github.com/bokub/gradient-string/issues",
77
"dependencies": {
8-
"chalk": "^2.1.0",
8+
"chalk": "^2.2.0",
99
"tinygradient": "^0.3.1"
1010
},
1111
"devDependencies": {

test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,22 @@ test('works fine', t => {
3636
'\u001b[91ma\u001b[39m\u001b[34mb\u001b[39m\u001b[32mc\u001b[39m'); // Red -> blue -> green (long arc)
3737
});
3838

39+
test('supports aliases', t => {
40+
t.is(g.cristal('Hello world'), g('#bdfff3', '#4ac29a')('Hello world'));
41+
t.is(g.pastel('Hello world'), g('#74ebd5', '#74ecd5')('Hello world', {interpolation: 'hsv', hsvSpin: 'long'}));
42+
});
43+
44+
test('multiline option works the same way on one line strings', t => {
45+
t.is(g('blue', 'white', 'red').multiline('abc'), g('blue', 'white', 'red')('abc'));
46+
t.is(g('red', 'green').multiline('abc', {interpolation: 'hsv'}), g('red', 'green')('abc', {interpolation: 'hsv'}));
47+
});
48+
49+
test('multiline option works fine', t => {
50+
t.is(g('orange', 'purple').multiline('hello\nworld'), g('orange', 'purple')('hello') + '\n' + g('orange', 'purple')('world'));
51+
t.is(g.atlas.multiline('abc\n\ndef'), g.atlas('abc') + '\n\n' + g.atlas('def'));
52+
t.not(g.rainbow.multiline('hi\nworld'), g.rainbow('hi') + '\n' + g.rainbow('world'));
53+
});
54+
3955
test('case insensitive options', t => {
4056
t.is(g('red', 'green')('abc', {interpolation: 'hsv', hsvSpin: 'long'}), g('red', 'green')('abc', {interpolation: 'HSV', hsvSpin: 'Long'}));
4157
});

0 commit comments

Comments
 (0)