Skip to content

Commit 957fc0b

Browse files
authored
Merge pull request #4 from webdeveric/feat/options
Allow `style` option to be an array
2 parents 234f4df + 87ca58a commit 957fc0b

16 files changed

+228
-60
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ jobs:
3131
- name: Installing dependencies
3232
run: pnpm install --frozen-lockfile
3333

34-
- name: Linting
35-
run: pnpm lint
36-
3734
- name: Type checking
3835
run: pnpm typecheck
3936

37+
- name: Linting
38+
run: pnpm lint
39+
4040
- name: Testing
4141
run: pnpm coverage
4242

example/index.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { randomInt } from 'node:crypto';
22
import { styleText } from 'node:util';
33

44
import { createConsole } from 'styled-json-console';
5+
import { mergeStyleOptions } from 'styled-json-console/mergeStyleOptions';
56

67
const myConsole = createConsole({
78
inspectOptions: {
@@ -37,9 +38,9 @@ const myConsole = createConsole({
3738
// stderr settings are merged with stdout settings so you can override only what you want
3839
{
3940
space: 2,
40-
style: {
41-
string: ['white', 'whiteBright'],
42-
},
41+
style: mergeStyleOptions(['whiteBright'], {
42+
number: ['magentaBright'],
43+
}),
4344
},
4445
],
4546
});
@@ -50,6 +51,7 @@ const data = {
5051
randomNumber: randomInt(0, 2 ** 32 - 1),
5152
example: true,
5253
json: JSON.stringify({ a: 1, b: [2], c: { d: 3, e: [4, 5] } }),
54+
nested: { a: 1, b: [2], c: { d: 3, e: [4, 5] } },
5355
};
5456

5557
myConsole.info(JSON.stringify(data));

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@
4848
"homepage": "https://github.com/webdeveric/styled-json-console/#readme",
4949
"packageManager": "pnpm@10.26.2+sha512.0e308ff2005fc7410366f154f625f6631ab2b16b1d2e70238444dd6ae9d630a8482d92a451144debc492416896ed16f7b114a86ec68b8404b2443869e68ffda6",
5050
"scripts": {
51-
"clean": "rimraf ./dist/",
51+
"clean": "rimraf ./dist/ ./cache/",
5252
"prebuild": "pnpm clean",
5353
"build": "tsc --build tsconfig.src.json --force",
54-
"typecheck": "tsc --build tsconfig.src.json tsconfig.test.json tsconfig.configs.json --verbose",
55-
"lint": "eslint ./*.{js,cjs,mjs,ts,cts,mts} ./src/ --ext .ts",
54+
"typecheck": "tsc --build tsconfig.json --verbose",
55+
"lint": "eslint ./*.{js,cjs,mjs,ts,cts,mts} ./src/ ./example/ --ext .ts",
5656
"test": "vitest --typecheck",
5757
"coverage": "vitest run --coverage --typecheck",
5858
"validate": "validate-package-exports --check --verify",

src/AnsiJsonWritable.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { Writable, type WritableOptions } from 'node:stream';
22

33
import { ansiHighlightJson } from './ansiHighlightJson.js';
44
import { isColorEnabled } from './isColorEnabled.js';
5-
import { Style, type StyleOptions } from './Style.js';
5+
import { Style } from './Style.js';
66

7-
import type { JsonReplacerFn } from './types.js';
7+
import type { JsonReplacerFn, StyleOptions, StyleTextFormatArray } from './types.js';
88

99
export type ModifyOutputFn = (output: string, style: Style) => string;
1010

@@ -13,7 +13,7 @@ export type AnsiJsonWritableOptions = WritableOptions & {
1313
space?: number | string;
1414
eol?: string;
1515
replacer?: JsonReplacerFn;
16-
styleOptions?: Partial<StyleOptions>;
16+
styleOptions?: Partial<StyleOptions> | StyleTextFormatArray;
1717
modifyOutput?: ModifyOutputFn;
1818
};
1919

src/Style.ts

Lines changed: 7 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,23 @@
11
import { styleText, type StyleTextOptions } from 'node:util';
22

3-
import type { StyleTextFormat } from './types.js';
4-
5-
export type StyleKeys =
6-
| 'string'
7-
| 'number'
8-
| 'boolean'
9-
| 'bracket'
10-
| 'comma'
11-
| 'colon'
12-
| 'quoteKey'
13-
| 'quoteString'
14-
| 'key'
15-
| 'null';
3+
import { defaultStyleOptions } from './defaults.js';
4+
import { mergeStyleOptions } from './mergeStyleOptions.js';
5+
6+
import type { StyleKey, StyleOptions, StyleTextFormat, StyleTextFormatArray } from './types.js';
167

178
export type StyleFn = (value: string, depth: number) => string;
189

1910
export type BaseStyle = {
20-
[K in StyleKeys]: StyleFn;
21-
};
22-
23-
export type StyleOptions = Record<
24-
StyleKeys,
25-
[item: StyleTextFormat, ...rest: StyleTextFormat[]] // At least one item
26-
>;
27-
28-
export const defaultStyleOptions: StyleOptions = {
29-
// content
30-
string: ['green'],
31-
number: ['yellowBright'],
32-
boolean: ['blueBright'],
33-
null: ['redBright'],
34-
35-
// structural
36-
bracket: ['white', 'blue', 'yellow', 'cyan', 'green', 'red'],
37-
comma: ['white'],
38-
colon: ['white'],
39-
40-
// quotes
41-
quoteKey: ['cyan'],
42-
quoteString: ['green'],
43-
44-
// keys
45-
key: ['cyan'],
11+
[K in StyleKey]: StyleFn;
4612
};
4713

4814
export class Style implements BaseStyle {
4915
readonly #options: StyleOptions;
5016

5117
readonly #styleTextOptions: StyleTextOptions = { validateStream: false };
5218

53-
constructor(options?: Partial<StyleOptions>) {
54-
this.#options = { ...defaultStyleOptions, ...options };
19+
constructor(options?: Partial<StyleOptions> | StyleTextFormatArray) {
20+
this.#options = mergeStyleOptions(defaultStyleOptions, options);
5521
}
5622

5723
#getStyleTextFormat(type: keyof StyleOptions, depth: number): StyleTextFormat {

src/createConsole.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { Console, type ConsoleConstructorOptions } from 'node:console';
22

33
import { AnsiJsonWritable, type ModifyOutputFn } from './AnsiJsonWritable.js';
4+
import { mergeStyleOptions } from './mergeStyleOptions.js';
45

5-
import type { StyleOptions } from './Style.js';
6-
import type { JsonReplacerFn } from './types.js';
6+
import type { JsonReplacerFn, StyleOptions, StyleTextFormatArray } from './types.js';
77

88
export type JsonConsoleOptions = {
9-
style?: Partial<StyleOptions>;
9+
style?: Partial<StyleOptions> | StyleTextFormatArray;
1010
space?: number | string;
1111
replacer?: JsonReplacerFn;
1212
};
@@ -28,10 +28,7 @@ export function createConsole(options: Partial<CreateConsoleOptions> = {}): Cons
2828
? {
2929
...stdOutJson,
3030
...json[1],
31-
style: {
32-
...stdOutJson?.style,
33-
...json[1]?.style,
34-
},
31+
style: mergeStyleOptions(stdOutJson?.style, json[1]?.style),
3532
}
3633
: json;
3734

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { describe, it, expect } from 'vitest';
2+
3+
import { createSimpleStyleOptions } from './createSimpleStyleOptions.js';
4+
5+
import type { StyleOptions } from './types.js';
6+
7+
describe('createSimpleStyleOptions', () => {
8+
it('creates style options with the given value for all style keys', () => {
9+
expect(createSimpleStyleOptions(['red'])).toEqual({
10+
boolean: ['red'],
11+
bracket: ['red'],
12+
colon: ['red'],
13+
comma: ['red'],
14+
key: ['red'],
15+
null: ['red'],
16+
number: ['red'],
17+
quoteKey: ['red'],
18+
quoteString: ['red'],
19+
string: ['red'],
20+
} satisfies StyleOptions);
21+
});
22+
});

src/createSimpleStyleOptions.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { defaultStyleOptions } from './defaults.js';
2+
import { isStyleKey } from './isStyleKey.js';
3+
4+
import type { StyleOptions, StyleTextFormatArray } from './types.js';
5+
6+
export function createSimpleStyleOptions(value: StyleTextFormatArray): StyleOptions {
7+
const options: StyleOptions = { ...defaultStyleOptions };
8+
9+
for (const key in options) {
10+
if (isStyleKey(key)) {
11+
options[key] = value;
12+
}
13+
}
14+
15+
return options;
16+
}

src/defaults.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import type { StyleOptions } from './types.js';
2+
3+
export const defaultStyleOptions: Readonly<StyleOptions> = {
4+
// content
5+
string: ['green'],
6+
number: ['yellowBright'],
7+
boolean: ['blueBright'],
8+
null: ['redBright'],
9+
10+
// structural
11+
bracket: ['white', 'blue', 'yellow', 'cyan', 'green', 'red'],
12+
comma: ['white'],
13+
colon: ['white'],
14+
15+
// quotes
16+
quoteKey: ['cyan'],
17+
quoteString: ['green'],
18+
19+
// keys
20+
key: ['cyan'],
21+
};

src/isStyleKey.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import { isStyleKey } from './isStyleKey.js';
4+
5+
describe('isStyleKey()', () => {
6+
it.each(['string', 'number', 'boolean', 'bracket', 'comma', 'colon', 'quoteKey', 'quoteString', 'key', 'null'])(
7+
'returns true for %j',
8+
(input) => {
9+
expect(isStyleKey(input)).toBe(true);
10+
},
11+
);
12+
13+
it.each([null, undefined, 42, {}, [], 'not valid'])('returns false for %j', (input) => {
14+
expect(isStyleKey(input)).toBe(false);
15+
});
16+
});

0 commit comments

Comments
 (0)