I am leveraging ansis and appreciate the work you've done here but I have a couple of pain points and I'd like to suggest some minor refactors to improve how the module is used and generally just provide a better experience overall.
Named Exports
The current approach is to have ansis export on the default but this is not always ideal. In order to obtain a single colour one needs to do the following:
import ansis from 'ansis';
console.log(`Print ${ansis.yellow('I am yellow')}`)
While this suffices, it can get a little cumbersome and a better option would be to provide an additional import/file that exposes the defaults as named exports, for example:
import { yellow } from 'ansis/colors';
console.log(`Print ${yellow('I am yellow')}`)
OR alternatively, you could expose the named exports directly and still preserve the default, eg:
import ansis, { red } from 'ansis';
console.log(`Print ${ansis.yellow('I am yellow')} and ${red('I am red')}`)
Supporting this is trivial, you can simply add them to the exports, eg:
// ....
const ansis = new Ansis();
export const {
cyan,
cyanBright,
red,
redBright,
green,
greenBright,
yellow,
yellowBright,
magenta,
magentaBright,
blue,
blueBright,
white,
whiteBright,
gray,
underline,
bold,
reset,
italic,
strike
// etc etc etc
} = ansis;
export default ansis
Improve Typings
It would be nice to have types available for additional usage. I have various functions which construct log output and accept colour parameters which I pass to ansis. In order for folks to take advantage of intellisense capabilities having a reference of the defaults would be a great help. Take the following sample:
import ansis from 'ansis'
export const write = (colour: string, message: string) => {
message += fn(message) // do something
console.log(ansis[colour](message);
}
Currently, there is no exposed type refs for colors that ansis provides. Where the parameter colour
expects a string
a far better approach is to have this available in the declaration, eg:
import ansis, { Colors } from 'ansis' // using US english for the sake of brevity
export const write = (colour: Colors, message: string) => {
message += fn(message) // do something
console.log(ansis[colour](message))
}
This is rather simple to provide, here is a starting point:
/**
* Default Colors
*/
export type Colors = (
| 'cyan'
| 'cyanBright'
| 'red'
| 'redBright'
| 'green'
| 'greenBright'
| 'yellow'
| 'yellowBright'
| 'magenta'
| 'magentaBright'
| 'blue'
| 'blueBright'
| 'white'
| 'whiteBright'
| 'gray'
| 'underline'
| 'bold'
| 'reset'
| 'italic'
| 'strike'
// etc etc etc
);
An even better approach would be:
type StringUnion<T, B extends string> = T | (B & Record<never, never>);
export type Colors = (
| 'cyan'
| 'cyanBright'
| 'red'
| 'redBright'
| 'green'
| 'greenBright'
| 'yellow'
| 'yellowBright'
| 'magenta'
| 'magentaBright'
| 'blue'
| 'blueBright'
| 'white'
| 'whiteBright'
| 'gray'
| 'underline'
| 'bold'
| 'reset'
| 'italic'
| 'strike'
// etc etc
)
export type ColorsExtend<T extends string> = StringUnion<Colors, T>;
The above ColorsExtend
would allow for consumers to extend the defaults with any custom colours generated in their projects, using the initial sample and the above types you could then do:
import ansis, { ColorsExtend } from 'ansis'
const pink = ansis.hex('#ff75d1');
const orange = ansis.hex('#FFAB40');
export const write = (colour: ColorsExtend<'pink' | 'orange'>, message: string) => {
message += fn(message) // do something
console.log(ansis[colour](message))
}
Thanks