diff --git a/index.js b/index.js index 05e62b3..ad9d4b3 100644 --- a/index.js +++ b/index.js @@ -22,6 +22,10 @@ function applyOptions(obj, options) { const scLevel = supportsColor ? supportsColor.level : 0; obj.level = options.level === undefined ? scLevel : options.level; obj.enabled = 'enabled' in options ? options.enabled : obj.level > 0; + + // By default, wrappers are empty strings + const defaultWrapper = {pre: '', post: ''}; + obj.wrapper = typeof options.wrapper === 'object' ? Object.assign({}, defaultWrapper, options.wrapper) : defaultWrapper; } function Chalk(options) { @@ -149,6 +153,9 @@ function build(_styles, _empty, key) { // See below for fix regarding invisible grey/dim combination on Windows builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey'; + // Setting the wrapper in case it is being used + builder.wrapper = this.wrapper; + // `__proto__` is used because we must return a function, but there is // no way to create a function with a different prototype builder.__proto__ = proto; // eslint-disable-line no-proto @@ -189,12 +196,15 @@ function applyStyle() { // Replace any instances already present with a re-opening code // otherwise only the part of the string until said closing code // will be colored, and the rest will simply be 'plain'. - str = code.open + str.replace(code.closeRe, code.open) + code.close; + const open = this.wrapper.pre + code.open + this.wrapper.post; + const close = this.wrapper.pre + code.close + this.wrapper.post; + + str = open + str.replace(code.closeRe, code.open) + close; // Close the styling before a linebreak and reopen // after next line to fix a bleed issue on macOS // https://github.com/chalk/chalk/pull/92 - str = str.replace(/\r?\n/g, `${code.close}$&${code.open}`); + str = str.replace(/\r?\n/g, `${close}$&${open}`); } // Reset the original `dim` if we changed it to work around the Windows dimmed gray issue diff --git a/readme.md b/readme.md index eb74603..2754499 100644 --- a/readme.md +++ b/readme.md @@ -149,6 +149,26 @@ Levels are as follows: 2. 256 color support 3. Truecolor support (16 million colors) +### chalk.wrapper + +The wrapper marks the unprintable characters. +A wrapper can be added to the styles, so you can escape characters or add marks to then. +By default, these wrappers are empty strings `""`. + +The wrappers object has two properties, `pre` and `post`. +For example: + +```js +const ctx = new chalk.constructor({wrapper: { + pre: '>', + post: '<', +}}); + +ctx.red('foo') // outputs "><" +``` + +This can be specially useful when escaping characters, using it into a _PS1_ string or debugging and outputing it into different terminals/TTYs. + ### chalk.supportsColor Detect whether the terminal [supports color](https://github.com/chalk/supports-color). Used internally and handled for you, but exposed for convenience. diff --git a/test/chalk.js b/test/chalk.js index 8480dad..d2add8d 100644 --- a/test/chalk.js +++ b/test/chalk.js @@ -6,7 +6,7 @@ require('./_supports-color')(__dirname); const m = require('..'); console.log('TERM:', process.env.TERM || '[none]'); -console.log('platform:', process.platform || '[unknown]'); +console.log('Platform:', process.platform || '[unknown]'); test('don\'t add any styling when called as the base function', t => { t.is(m('foo'), 'foo'); diff --git a/test/wrapper.js b/test/wrapper.js new file mode 100644 index 0000000..156e4eb --- /dev/null +++ b/test/wrapper.js @@ -0,0 +1,25 @@ +// Import path from 'path'; +import test from 'ava'; +// Import execa from 'execa'; + +// Spoof supports-color +require('./_supports-color')(__dirname); + +const m = require('..'); + +m.wrapper = { + pre: '@', + post: '#' +}; + +test('add wrapper to underline', t => { + t.is(m.underline('foo'), '@\u001B[4m#foo@\u001B[24m#'); +}); + +test('add wrapper to color', t => { + t.is(m.red('foo'), '@\u001B[31m#foo@\u001B[39m#'); +}); + +test('add wrapper to bgColor', t => { + t.is(m.bgRed('foo'), '@\u001B[41m#foo@\u001B[49m#'); +}); diff --git a/types/index.d.ts b/types/index.d.ts index b4e4dc5..c5a4708 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -11,6 +11,12 @@ export const enum Level { export interface ChalkOptions { enabled?: boolean; level?: Level; + wrapper?: Wrapper; +} + +export interface Wrapper { + pre: String, + post: String } export interface ChalkConstructor { @@ -31,6 +37,7 @@ export interface Chalk { constructor: ChalkConstructor; enabled: boolean; level: Level; + wrapper: Wrapper; rgb(r: number, g: number, b: number): this; hsl(h: number, s: number, l: number): this; hsv(h: number, s: number, v: number): this;