Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply visual styling to echo commands used in npm scripts via package.json

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.

like image 369
Glynn Smith Avatar asked May 08 '18 05:05

Glynn Smith


People also ask

How do I run a npm script in package json?

To define an NPM script, set its name and write the script under the 'scripts' property of your package. json file: To execute your Script, use the 'npm run <NAME-OF-YOUR-SCRIPT>' command. Some predefined aliases convert to npm run, like npm test or npm start, you can use them interchangeably.

What is scripts in package json?

The "scripts" property of your package. json file supports a number of built-in scripts and their preset life cycle events as well as arbitrary scripts. These all can be executed by running npm run-script <stage> or npm run <stage> for short.


1 Answers

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):

enter image description here

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):

enter image description here

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:

  1. 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.

  2. 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.

    enter image description here

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]
  1. 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.

  2. [--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.

  3. [--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        │
    └─────────────────────────┘
    
  4. [--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.

like image 90
RobC Avatar answered Oct 14 '22 06:10

RobC