Have recently put together a build tool with npm
and package.json
scripts, and I have a few echo
commands to state which parts of the pipeline are currently running.
For example (from my package.json
):
{
"scripts": {
"clean": "rimraf a-directory/",
"preclean": "echo \"\n[ Cleaning build directories ]\n\""
}
}
When I Bash: npm run clean
it prints my echo
message, and then cleans the appropriate directory.
I'd like to change colour, font weight, background text colour to make these echo
statements stand out and be more informative at a glance, but I've struggled even finding a starting point that can set me off being able to do this.
There's lots of info about doing this in regular CLI/Bash scripts, via grunt
and gulp
, or via JS scripts, but nothing I've found is attempting it from the scripts section of package.json
.
What am I missing? All help appreciated.
Many thanks.
Consoles/terminals typically provide support for ANSI/VT100 Control sequences, so it's possible to use these codes to control font colour, font weight, background colour, etc.
For a Bash only solution refer to the Bash (MacOS/Linux/ etc..) section below.
However, if cross platform support is required then follow the solution described in the Cross Platform section below.
Bash (MacOS/Linux/ etc..)
Important Note: The following will not work successfully on non-bash consoles, such as Windows Command Prompt (i.e. cmd.exe) or PowerShell.
This example npm-script below:
"scripts": {
"clean": "rimraf a-directory/",
"preclean": "echo \"\\x1b[104m\\x1b[97m\n[ Cleaning build directories ]\n\\x1b[0m\""
}
...will log the something like the following in your console when running npm run clean
(i.e. white text with a blue colored background):
Breakdown of the necessary syntax/codes:
<Esc> characters
┌─────────┬────┴─────────┐
│ │ │
┌─┴─┐ ┌─┴─┐ ┌─┴─┐
\\x1b[104m\\x1b[97m Mssg \\x1b[0m
└─┬─┘ └─┬┘└─┬─┘ └┬┘
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ Reset all attributes
│ │ │
│ │ Your Message
│ │
│ White Text
│
Light blue background
Further examples:
The following example npm-scripts provide further examples:
"scripts": {
"a": "echo \"\\x1b[1m\\x1b[39mBold Text\\x1b[0m\"",
"b": "echo \"\\x1b[91mLight Red Text\\x1b[0m\"",
"c": "echo \"\\x1b[94mLight Blue Text\\x1b[0m\"",
"d": "echo \"\\x1b[92mLight Green Text\\x1b[0m\"",
"e": "echo \"\\x1b[4m\\x1b[91mLight Red Underlined Text\\x1b[0m\"",
"f": "echo \"\\x1b[101m\\x1b[97mLight Red Background and White Text\\x1b[0m\"",
"g": "echo \"\\x1b[104m\\x1b[97mLight Blue Background and White Text\\x1b[0m\"",
"h": "echo \"\\x1b[30m\\x1b[103mLight Yellow Background and Black Text\\x1b[0m\"",
"i": "echo \"\\x1b[97m\\x1b[100mDark Gray Background and White Text\\x1b[0m\"",
"bash-echo-all": "npm run a -s && npm run b -s && npm run c -s && npm run d -s && npm run e -s && npm run f -s && npm run g -s && npm run h -s && npm run i -s"
},
Running npm run bash-echo-all -s
using the scripts above will output the following to your console (the -s
option just makes npm log a bit less):
A more comprehensive list of codes can be found at the link provided at the top of this post, (or see codes listed in Cross Platform section below), but remember not all ANSI/VT100 Control sequences are supported.
Cross Platform
For a cross-platform solution, (one which works successfully with Bash, Windows Command Prompt / cmd.exe, and PowerShell etc..), you'll need to create a nodejs utility script to handle the logging. This nodejs script can then be invoked via your npm-scripts
.
The following steps describe how this can be achieved:
Create a nodejs utility script as follows:
echo.js
const args = process.argv;
const mssg = args[2];
const opts = [
'-s', '--set',
'-b', '--bg-color',
'-f', '--font-color'];
function excapeAnsiCode(code) {
return '\x1b[' + code + 'm';
}
const ansiStyles = opts.map(function (opt) {
return args.indexOf(opt) > -1
? excapeAnsiCode(args[args.indexOf(opt) +1])
: '';
});
console.log('%s%s%s', ansiStyles.join(''), mssg, '\x1b[0m');
Let's name the file echo.js
and save it in the root of your project directory, i.e. in the same folder where package.json
is stored.
Then, given your example, let's add a npm-script
to package.json
as follows:
"scripts": {
"clean": "rimraf a-directory/",
"preclean": "node echo \"[ Cleaning build directories ]\" --bg-color 104 --font-color 97"
}
When running npm run clean
you'll see the same message logged to your console as before when using the bash only solution, i.e. white text with a blue colored background.
Overview of usage syntax for invoking echo.js
via npm-scripts
node echo \"message\" [[-s|--set] number] [[-b|--bg-color] number] [[-f|--font-color] number]
node echo \"message\"
The node echo \"message\"
part is mandatory. The message
is where you enter your message to be logged and it must be wrapped in escaped double quotes \"...\"
to prevent splitting.
The remaining parts, which are for the purpose of formatting/styling, are all optional and can be defined in any order. However, when used, they must proceed after the initial node echo \"message\"
part, and be separated by a single space.
[--set|-s
]
The --set
option, or it's shorthand equivalent -s
, followed by a single space, and one of the following ANSI codes can be used to specify general formatting:
┌─────────────────────────┐
│ Code Description │
├─────────────────────────┤
│ 1 Bold/Bright │
│ 2 Dim │
│ 4 Underlined │
│ 5 Blink │
│ 7 Reverse/invert │
│ 8 Hidden │
└─────────────────────────┘
Note: Codes 1
and 4
worked successfully with Bash, however they were not supported by Windows Command Prompt and Powershell. So if repeatability is important across platforms I recommend avoiding use of the --set
|-s
option entirely.
[--bg-color|-b
]
The --bg-color
option, or it's shorthand equivalent -b
, followed by a single space, and one of the following ANSI codes can be used to specify the background color:
┌─────────────────────────┐
│ Code Background Color │
├─────────────────────────┤
│ 49 Default │
│ 40 Black │
│ 41 Red │
│ 42 Green │
│ 43 Yellow │
│ 44 Blue │
│ 45 Magenta │
│ 46 Cyan │
│ 47 Light Gray │
│ 100 Dark Gray │
│ 101 Light Red │
│ 102 Light Green │
│ 103 Light Yellow │
│ 104 Light Blue │
│ 105 Light Magenta │
│ 106 Light Cyan │
│ 107 White Cyan │
└─────────────────────────┘
[--font-color|-f
]
The --font-color
option, or it's shorthand equivalent -f
, followed by a single space, and one of the following ANSI codes can be used to specify the font color:
┌─────────────────────────┐
│ Code Font Color │
├─────────────────────────┤
│ 39 Default │
│ 30 Black │
│ 31 Red │
│ 32 Green │
│ 33 Yellow │
│ 34 Blue │
│ 35 Magenta │
│ 36 Cyan │
│ 37 Light Gray │
│ 90 Dark Gray │
│ 91 Light Red │
│ 92 Light Green │
│ 93 Light Yellow │
│ 94 Light Blue │
│ 95 Light Magenta │
│ 96 Light Cyan │
│ 97 White Cyan │
└─────────────────────────┘
Further examples:
The following example scripts provide further examples:
"scripts": {
"r": "node echo \"Bold Text\" -s 1",
"s": "node echo \"Light Red Text\" -f 91",
"t": "node echo \"Light Blue Text\" -f 94",
"u": "node echo \"Light Green Text\" -f 92",
"v": "node echo \"Light Red Underlined Text\" -s 4 -f 91",
"w": "node echo \"Light Red Background and White Text\" -b 101 -f 97",
"x": "node echo \"Light Blue Background and White Text\" -b 104 -f 97",
"y": "node echo \"Light Yellow Background and Black Text\" -f 30 -b 103",
"z": "node echo \"Dark Gray Background and White Text\" -b 100 -f 97",
"node-echo-all": "npm run r -s && npm run s -s && npm run t -s && npm run u -s && npm run v -s && npm run w -s && npm run x -s && npm run y -s && npm run z -s"
},
Running npm run node-echo-all -s
using the scripts above will output the the same results as shown in the Bash (MacOS/Linux/ etc..) section above.
For brevity these scripts (above) utilize the shorthand -s
, -b
, and -f
options. However they can be substituted with their longhand equivalents --set
, --bg-color
, and --font-color
respectively if necessary to make your code more human readable.