@peteanderson/ansi 3.7.1 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/dist/cjs/ansi.d.ts +7 -3
- package/dist/cjs/ansi.d.ts.map +1 -1
- package/dist/cjs/ansi.js +6 -1
- package/dist/cjs/ansi.js.map +1 -1
- package/dist/cjs/code.d.ts +10 -0
- package/dist/cjs/code.d.ts.map +1 -0
- package/dist/cjs/code.js +9 -0
- package/dist/cjs/code.js.map +1 -0
- package/dist/cjs/cursor.js +30 -30
- package/dist/cjs/cursor.js.map +1 -1
- package/dist/cjs/index.d.ts +12 -7
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/ins-del.js +16 -16
- package/dist/cjs/ins-del.js.map +1 -1
- package/dist/cjs/package.json +25 -0
- package/dist/cjs/scroll.js +9 -9
- package/dist/cjs/scroll.js.map +1 -1
- package/dist/cjs/sgr/chain/attach.d.ts +5 -0
- package/dist/cjs/sgr/chain/attach.d.ts.map +1 -0
- package/dist/cjs/sgr/chain/attach.js +10 -0
- package/dist/cjs/sgr/chain/attach.js.map +1 -0
- package/dist/cjs/sgr/chain/build.d.ts +8 -0
- package/dist/cjs/sgr/chain/build.d.ts.map +1 -0
- package/dist/cjs/sgr/chain/build.js +15 -0
- package/dist/cjs/sgr/chain/build.js.map +1 -0
- package/dist/cjs/sgr/chain/chain.d.ts +13 -0
- package/dist/cjs/sgr/chain/chain.d.ts.map +1 -0
- package/dist/cjs/sgr/chain/chain.js +36 -0
- package/dist/cjs/sgr/chain/chain.js.map +1 -0
- package/dist/cjs/sgr/chain/index.d.ts +5 -0
- package/dist/cjs/sgr/chain/index.d.ts.map +1 -0
- package/dist/cjs/sgr/chain/index.js +20 -0
- package/dist/cjs/sgr/chain/index.js.map +1 -0
- package/dist/cjs/sgr/chain/keys.d.ts +5 -0
- package/dist/cjs/sgr/chain/keys.d.ts.map +1 -0
- package/dist/cjs/sgr/chain/keys.js +8 -0
- package/dist/cjs/sgr/chain/keys.js.map +1 -0
- package/dist/cjs/sgr/color/channel.d.ts +29 -3
- package/dist/cjs/sgr/color/channel.d.ts.map +1 -1
- package/dist/cjs/sgr/color/channel.js +8 -8
- package/dist/cjs/sgr/color/channel.js.map +1 -1
- package/dist/cjs/sgr/color/color.d.ts +9 -3
- package/dist/cjs/sgr/color/color.d.ts.map +1 -1
- package/dist/cjs/sgr/color/color.js +6 -10
- package/dist/cjs/sgr/color/color.js.map +1 -1
- package/dist/cjs/sgr/color/context.d.ts +12 -8
- package/dist/cjs/sgr/color/context.d.ts.map +1 -1
- package/dist/cjs/sgr/color/context.js +28 -18
- package/dist/cjs/sgr/color/context.js.map +1 -1
- package/dist/cjs/sgr/color/rgb.d.ts +7 -4
- package/dist/cjs/sgr/color/rgb.d.ts.map +1 -1
- package/dist/cjs/sgr/color/rgb.js +12 -12
- package/dist/cjs/sgr/color/rgb.js.map +1 -1
- package/dist/cjs/sgr/combine.d.ts +1 -1
- package/dist/cjs/sgr/combine.d.ts.map +1 -1
- package/dist/cjs/sgr/context.d.ts +16 -0
- package/dist/cjs/sgr/context.d.ts.map +1 -0
- package/dist/cjs/sgr/context.js +43 -0
- package/dist/cjs/sgr/context.js.map +1 -0
- package/dist/cjs/sgr/format.d.ts +19 -0
- package/dist/cjs/sgr/format.d.ts.map +1 -0
- package/dist/cjs/sgr/format.js +35 -0
- package/dist/cjs/sgr/format.js.map +1 -0
- package/dist/cjs/sgr/index.d.ts +3 -1
- package/dist/cjs/sgr/index.d.ts.map +1 -1
- package/dist/cjs/sgr/index.js +3 -0
- package/dist/cjs/sgr/index.js.map +1 -1
- package/dist/cjs/sgr/reset.js +2 -2
- package/dist/cjs/sgr/reset.js.map +1 -1
- package/dist/cjs/sgr/sgr.d.ts +10 -2
- package/dist/cjs/sgr/sgr.d.ts.map +1 -1
- package/dist/cjs/sgr/sgr.js +7 -32
- package/dist/cjs/sgr/sgr.js.map +1 -1
- package/dist/cjs/sgr/style.d.ts +9 -2
- package/dist/cjs/sgr/style.d.ts.map +1 -1
- package/dist/cjs/sgr/style.js +13 -12
- package/dist/cjs/sgr/style.js.map +1 -1
- package/dist/cjs/simplify/simplify.d.ts.map +1 -1
- package/dist/cjs/simplify/simplify.js +4 -7
- package/dist/cjs/simplify/simplify.js.map +1 -1
- package/dist/cjs/slice.js +3 -3
- package/dist/cjs/slice.js.map +1 -1
- package/dist/cjs/strip.js +3 -3
- package/dist/cjs/strip.js.map +1 -1
- package/dist/cjs/terminal.js +13 -13
- package/dist/cjs/terminal.js.map +1 -1
- package/dist/cjs/types.d.ts +2 -1
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/utils.d.ts +3 -1
- package/dist/cjs/utils.d.ts.map +1 -1
- package/dist/cjs/utils.js +9 -6
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/ansi.d.ts +7 -3
- package/dist/esm/ansi.d.ts.map +1 -1
- package/dist/esm/ansi.js +3 -2
- package/dist/esm/ansi.js.map +1 -1
- package/dist/esm/code.d.ts +10 -0
- package/dist/esm/code.d.ts.map +1 -0
- package/dist/esm/code.js +6 -0
- package/dist/esm/code.js.map +1 -0
- package/dist/esm/cursor.js +5 -5
- package/dist/esm/cursor.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/ins-del.js +1 -1
- package/dist/esm/ins-del.js.map +1 -1
- package/dist/esm/package.json +25 -1
- package/dist/esm/scroll.js +3 -3
- package/dist/esm/scroll.js.map +1 -1
- package/dist/esm/sgr/chain/attach.d.ts +5 -0
- package/dist/esm/sgr/chain/attach.d.ts.map +1 -0
- package/dist/esm/sgr/chain/attach.js +6 -0
- package/dist/esm/sgr/chain/attach.js.map +1 -0
- package/dist/esm/sgr/chain/build.d.ts +8 -0
- package/dist/esm/sgr/chain/build.d.ts.map +1 -0
- package/dist/esm/sgr/chain/build.js +12 -0
- package/dist/esm/sgr/chain/build.js.map +1 -0
- package/dist/esm/sgr/chain/chain.d.ts +13 -0
- package/dist/esm/sgr/chain/chain.d.ts.map +1 -0
- package/dist/esm/sgr/chain/chain.js +33 -0
- package/dist/esm/sgr/chain/chain.js.map +1 -0
- package/dist/esm/sgr/chain/index.d.ts +5 -0
- package/dist/esm/sgr/chain/index.d.ts.map +1 -0
- package/dist/esm/sgr/chain/index.js +4 -0
- package/dist/esm/sgr/chain/index.js.map +1 -0
- package/dist/esm/sgr/chain/keys.d.ts +5 -0
- package/dist/esm/sgr/chain/keys.d.ts.map +1 -0
- package/dist/esm/sgr/chain/keys.js +5 -0
- package/dist/esm/sgr/chain/keys.js.map +1 -0
- package/dist/esm/sgr/color/channel.d.ts +29 -3
- package/dist/esm/sgr/color/channel.d.ts.map +1 -1
- package/dist/esm/sgr/color/channel.js +9 -9
- package/dist/esm/sgr/color/channel.js.map +1 -1
- package/dist/esm/sgr/color/color.d.ts +9 -3
- package/dist/esm/sgr/color/color.d.ts.map +1 -1
- package/dist/esm/sgr/color/color.js +4 -10
- package/dist/esm/sgr/color/color.js.map +1 -1
- package/dist/esm/sgr/color/context.d.ts +12 -8
- package/dist/esm/sgr/color/context.d.ts.map +1 -1
- package/dist/esm/sgr/color/context.js +27 -17
- package/dist/esm/sgr/color/context.js.map +1 -1
- package/dist/esm/sgr/color/rgb.d.ts +7 -4
- package/dist/esm/sgr/color/rgb.d.ts.map +1 -1
- package/dist/esm/sgr/color/rgb.js +12 -12
- package/dist/esm/sgr/color/rgb.js.map +1 -1
- package/dist/esm/sgr/combine.d.ts +1 -1
- package/dist/esm/sgr/combine.d.ts.map +1 -1
- package/dist/esm/sgr/context.d.ts +16 -0
- package/dist/esm/sgr/context.d.ts.map +1 -0
- package/dist/esm/sgr/context.js +39 -0
- package/dist/esm/sgr/context.js.map +1 -0
- package/dist/esm/sgr/format.d.ts +19 -0
- package/dist/esm/sgr/format.d.ts.map +1 -0
- package/dist/esm/sgr/format.js +32 -0
- package/dist/esm/sgr/format.js.map +1 -0
- package/dist/esm/sgr/index.d.ts +3 -1
- package/dist/esm/sgr/index.d.ts.map +1 -1
- package/dist/esm/sgr/index.js +1 -0
- package/dist/esm/sgr/index.js.map +1 -1
- package/dist/esm/sgr/reset.js +1 -1
- package/dist/esm/sgr/reset.js.map +1 -1
- package/dist/esm/sgr/sgr.d.ts +10 -2
- package/dist/esm/sgr/sgr.d.ts.map +1 -1
- package/dist/esm/sgr/sgr.js +7 -32
- package/dist/esm/sgr/sgr.js.map +1 -1
- package/dist/esm/sgr/style.d.ts +9 -2
- package/dist/esm/sgr/style.d.ts.map +1 -1
- package/dist/esm/sgr/style.js +12 -12
- package/dist/esm/sgr/style.js.map +1 -1
- package/dist/esm/simplify/simplify.d.ts.map +1 -1
- package/dist/esm/simplify/simplify.js +3 -6
- package/dist/esm/simplify/simplify.js.map +1 -1
- package/dist/esm/slice.js +1 -1
- package/dist/esm/slice.js.map +1 -1
- package/dist/esm/strip.js +1 -1
- package/dist/esm/strip.js.map +1 -1
- package/dist/esm/terminal.js +1 -1
- package/dist/esm/terminal.js.map +1 -1
- package/dist/esm/types.d.ts +2 -1
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/utils.d.ts +3 -1
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/esm/utils.js +7 -5
- package/dist/esm/utils.js.map +1 -1
- package/package.json +13 -5
- package/src/ansi.ts +3 -2
- package/src/code.ts +9 -0
- package/src/cursor.ts +5 -5
- package/src/index.ts +1 -1
- package/src/ins-del.ts +1 -1
- package/src/require.ts +3 -3
- package/src/scroll.ts +3 -3
- package/src/sgr/chain/attach.ts +13 -0
- package/src/sgr/chain/build.ts +25 -0
- package/src/sgr/chain/chain.ts +60 -0
- package/src/sgr/chain/index.ts +5 -0
- package/src/sgr/chain/keys.ts +8 -0
- package/src/sgr/color/channel.ts +47 -19
- package/src/sgr/color/color.ts +14 -19
- package/src/sgr/color/context.ts +37 -31
- package/src/sgr/color/rgb.ts +21 -20
- package/src/sgr/combine.ts +1 -1
- package/src/sgr/context.ts +68 -0
- package/src/sgr/format.ts +72 -0
- package/src/sgr/index.ts +4 -2
- package/src/sgr/reset.ts +1 -1
- package/src/sgr/sgr.ts +21 -49
- package/src/sgr/style.ts +31 -21
- package/src/simplify/simplify.ts +3 -6
- package/src/slice.ts +1 -1
- package/src/strip.ts +1 -1
- package/src/terminal.ts +1 -1
- package/src/types.ts +2 -1
- package/src/utils.ts +12 -7
- package/dist/cjs/sgr/format-builder.d.ts +0 -3
- package/dist/cjs/sgr/format-builder.d.ts.map +0 -1
- package/dist/cjs/sgr/format-builder.js +0 -34
- package/dist/cjs/sgr/format-builder.js.map +0 -1
- package/dist/cjs/sgr/types.d.ts +0 -61
- package/dist/cjs/sgr/types.d.ts.map +0 -1
- package/dist/cjs/sgr/types.js +0 -3
- package/dist/cjs/sgr/types.js.map +0 -1
- package/dist/esm/sgr/format-builder.d.ts +0 -3
- package/dist/esm/sgr/format-builder.d.ts.map +0 -1
- package/dist/esm/sgr/format-builder.js +0 -30
- package/dist/esm/sgr/format-builder.js.map +0 -1
- package/dist/esm/sgr/types.d.ts +0 -61
- package/dist/esm/sgr/types.d.ts.map +0 -1
- package/dist/esm/sgr/types.js +0 -2
- package/dist/esm/sgr/types.js.map +0 -1
- package/src/sgr/format-builder.ts +0 -52
- package/src/sgr/types.ts +0 -93
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {makeColor} from "../color";
|
|
2
|
+
import {combineCodes} from "../combine";
|
|
3
|
+
import {makeStyle} from "../style";
|
|
4
|
+
|
|
5
|
+
import type {Color} from "../color";
|
|
6
|
+
import type {FormatContext} from "../context";
|
|
7
|
+
import type {FormatBase} from "../format";
|
|
8
|
+
import type {Style} from "../style";
|
|
9
|
+
import type {ChainKey} from "./keys";
|
|
10
|
+
|
|
11
|
+
export type Chain<Keys extends ChainKey> = Color<Keys> & Style<Keys>;
|
|
12
|
+
|
|
13
|
+
export function makeChain<Keys extends ChainKey>(
|
|
14
|
+
context : FormatContext<Keys>,
|
|
15
|
+
baseFormat : FormatBase,
|
|
16
|
+
): Chain<Keys> {
|
|
17
|
+
const parentCodes = context.parentCodes ? {
|
|
18
|
+
open : combineCodes(context.parentCodes.open, baseFormat.codes.open),
|
|
19
|
+
close : combineCodes(baseFormat.codes.close, context.parentCodes.close),
|
|
20
|
+
} : baseFormat.codes;
|
|
21
|
+
|
|
22
|
+
const chainedContext: FormatContext<Keys> = {...context, parentCodes};
|
|
23
|
+
|
|
24
|
+
return {...makeColor(chainedContext), ...makeStyle(chainedContext)};
|
|
25
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {define, ownProperties} from "@peteanderson/props";
|
|
2
|
+
import {getContext} from "../context";
|
|
3
|
+
import {attachChain} from "./attach";
|
|
4
|
+
import {allKeys} from "./keys";
|
|
5
|
+
|
|
6
|
+
import type {Features} from "#features";
|
|
7
|
+
import type {Format, FormatBase} from "../format";
|
|
8
|
+
import type {ChainKey} from "./keys";
|
|
9
|
+
|
|
10
|
+
function cloneFormatBase(baseFormat: FormatBase): FormatBase {
|
|
11
|
+
const clone = (text: string) => baseFormat(text);
|
|
12
|
+
const descriptors = ownProperties(baseFormat);
|
|
13
|
+
|
|
14
|
+
delete descriptors.and;
|
|
15
|
+
|
|
16
|
+
return define(clone, descriptors);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function keysMatch(a: ReadonlySet<ChainKey>, b: ReadonlySet<ChainKey>): boolean {
|
|
20
|
+
if (a.size !== b.size)
|
|
21
|
+
return false;
|
|
22
|
+
|
|
23
|
+
for (const key of a)
|
|
24
|
+
if (!b.has(key))
|
|
25
|
+
return false;
|
|
26
|
+
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
type ChainArgs<Keys extends ChainKey> = [
|
|
31
|
+
keys : ReadonlySet<Keys>,
|
|
32
|
+
baseFormat : FormatBase,
|
|
33
|
+
features? : Features,
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
type OverloadedArgs<Keys extends ChainKey> = [FormatBase, Features?] | ChainArgs<Keys>;
|
|
37
|
+
|
|
38
|
+
const resolveArgs = <Keys extends ChainKey>(args: OverloadedArgs<Keys>): ChainArgs<Keys> =>
|
|
39
|
+
args.length === 1 ?
|
|
40
|
+
[allKeys as ReadonlySet<Keys>, args[0], undefined] :
|
|
41
|
+
args.length === 2 ?
|
|
42
|
+
typeof args[0] === "function"
|
|
43
|
+
? [allKeys as ReadonlySet<Keys>, ...args as [FormatBase]]
|
|
44
|
+
: args as ChainArgs<Keys> :
|
|
45
|
+
args as ChainArgs<Keys>;
|
|
46
|
+
|
|
47
|
+
export function chain(baseFormat: FormatBase, features?: Features): Format<ChainKey>;
|
|
48
|
+
export function chain<Keys extends ChainKey = ChainKey>(...args: ChainArgs<Keys>): Format<Keys>;
|
|
49
|
+
|
|
50
|
+
export function chain<Keys extends ChainKey>(...args: OverloadedArgs<Keys>): Format<Keys> {
|
|
51
|
+
const [keys, baseFormat, features] = resolveArgs(args);
|
|
52
|
+
|
|
53
|
+
let context = getContext(baseFormat, features);
|
|
54
|
+
if (!keysMatch(context.keys, keys))
|
|
55
|
+
context = {...context, keys};
|
|
56
|
+
|
|
57
|
+
return attachChain(context, cloneFormatBase(baseFormat));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type AddChain = typeof chain;
|
package/src/sgr/color/channel.ts
CHANGED
|
@@ -1,10 +1,41 @@
|
|
|
1
|
-
import {csi}
|
|
2
|
-
import {lazy}
|
|
3
|
-
import {
|
|
4
|
-
import {makeRGB, makeX256}
|
|
1
|
+
import {csi} from "#utils";
|
|
2
|
+
import {lazy} from "../lazy";
|
|
3
|
+
import {buildChannelContext} from "./context";
|
|
4
|
+
import {makeRGB, makeX256} from "./rgb";
|
|
5
5
|
|
|
6
|
-
import type {
|
|
7
|
-
import type {
|
|
6
|
+
import type {ChainKey} from "../chain";
|
|
7
|
+
import type {FormatContext} from "../context";
|
|
8
|
+
import type {Format} from "../format";
|
|
9
|
+
import type {ColorKey} from "./color";
|
|
10
|
+
|
|
11
|
+
export interface Channel<Keys extends ChainKey = ChainKey> {
|
|
12
|
+
black : Format<Keys>;
|
|
13
|
+
red : Format<Keys>;
|
|
14
|
+
green : Format<Keys>;
|
|
15
|
+
yellow : Format<Keys>;
|
|
16
|
+
blue : Format<Keys>;
|
|
17
|
+
magenta : Format<Keys>;
|
|
18
|
+
cyan : Format<Keys>;
|
|
19
|
+
white : Format<Keys>;
|
|
20
|
+
|
|
21
|
+
brightBlack : Format<Keys>;
|
|
22
|
+
brightRed : Format<Keys>;
|
|
23
|
+
brightGreen : Format<Keys>;
|
|
24
|
+
brightYellow : Format<Keys>;
|
|
25
|
+
brightBlue : Format<Keys>;
|
|
26
|
+
brightMagenta : Format<Keys>;
|
|
27
|
+
brightCyan : Format<Keys>;
|
|
28
|
+
brightWhite : Format<Keys>;
|
|
29
|
+
|
|
30
|
+
rgb: (r: number, g: number, b: number) => Format<Keys>;
|
|
31
|
+
|
|
32
|
+
x256: {
|
|
33
|
+
(code: number): Format<Keys>;
|
|
34
|
+
(r: number, g: number, b: number): Format<Keys>;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
default: string,
|
|
38
|
+
}
|
|
8
39
|
|
|
9
40
|
const colors = [
|
|
10
41
|
"black",
|
|
@@ -17,27 +48,24 @@ const colors = [
|
|
|
17
48
|
"white",
|
|
18
49
|
] as const;
|
|
19
50
|
|
|
20
|
-
export function makeChannel(
|
|
21
|
-
|
|
22
|
-
makeFormatter : FormatBuilder,
|
|
23
|
-
style : Style,
|
|
24
|
-
colorDepth : ColorDepth,
|
|
51
|
+
export function makeChannel<Keys extends ChainKey>(
|
|
52
|
+
formatContext : FormatContext<Keys>,
|
|
25
53
|
channel : ColorKey,
|
|
26
|
-
): Channel {
|
|
27
|
-
const
|
|
28
|
-
const {build, bright,
|
|
54
|
+
): Channel<Keys> {
|
|
55
|
+
const channelContext = buildChannelContext(formatContext, channel);
|
|
56
|
+
const {build, bright, close, offset} = channelContext;
|
|
29
57
|
|
|
30
58
|
const rtn = {
|
|
31
|
-
rgb : makeRGB(
|
|
32
|
-
x256 : makeX256(
|
|
33
|
-
default :
|
|
34
|
-
} as Channel
|
|
59
|
+
rgb : makeRGB(channelContext),
|
|
60
|
+
x256 : makeX256(channelContext),
|
|
61
|
+
default : csi(close, "m"),
|
|
62
|
+
} as unknown as Channel<Keys>;
|
|
35
63
|
|
|
36
64
|
for (let i = 0; i < colors.length; i++) {
|
|
37
65
|
const color = colors[i];
|
|
38
66
|
const brightColor = `bright${color[0].toUpperCase()}${color.slice(1)}`;
|
|
39
67
|
|
|
40
|
-
lazy.add(rtn, color, () => build(
|
|
68
|
+
lazy.add(rtn, color, () => build(offset(i)));
|
|
41
69
|
lazy.add(rtn, brightColor, () => bright(i));
|
|
42
70
|
}
|
|
43
71
|
|
package/src/sgr/color/color.ts
CHANGED
|
@@ -1,29 +1,24 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
1
|
import {lazy} from "../lazy";
|
|
4
2
|
import {makeChannel} from "./channel";
|
|
5
3
|
|
|
6
|
-
import type {
|
|
7
|
-
import type {
|
|
4
|
+
import type {ChainKey} from "../chain";
|
|
5
|
+
import type {FormatContext} from "../context";
|
|
6
|
+
import type {Channel} from "./channel";
|
|
7
|
+
|
|
8
|
+
export const channels = ["fg", "bg"] as const;
|
|
9
|
+
|
|
10
|
+
export type ColorKey = typeof channels[number];
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
export type Color<Keys extends ChainKey = ChainKey> = {
|
|
13
|
+
[K in Extract<ColorKey, Keys>]: Channel<Exclude<Keys, K>>;
|
|
14
|
+
};
|
|
10
15
|
|
|
11
|
-
export function makeColor(
|
|
12
|
-
|
|
13
|
-
makeFormatter : FormatBuilder,
|
|
14
|
-
style : Style,
|
|
15
|
-
colorDepth : ColorDepth,
|
|
16
|
-
): Color<any> {
|
|
17
|
-
const rtn = {} as Color<any>;
|
|
16
|
+
export function makeColor<Keys extends ChainKey>(context: FormatContext<Keys>): Color<Keys> {
|
|
17
|
+
const rtn = {} as Color<Keys>;
|
|
18
18
|
|
|
19
19
|
for (const channel of channels) {
|
|
20
|
-
if (keys.has(channel))
|
|
21
|
-
lazy.add(rtn, channel, () =>
|
|
22
|
-
const newKeys = new Set(keys);
|
|
23
|
-
newKeys.delete(channel);
|
|
24
|
-
return makeChannel(newKeys, makeFormatter, style, colorDepth, channel);
|
|
25
|
-
});
|
|
26
|
-
}
|
|
20
|
+
if (context.keys.has(channel as Keys))
|
|
21
|
+
lazy.add(rtn, channel, () => makeChannel(context.removeKey(channel as Keys), channel));
|
|
27
22
|
}
|
|
28
23
|
|
|
29
24
|
return rtn;
|
package/src/sgr/color/context.ts
CHANGED
|
@@ -1,46 +1,52 @@
|
|
|
1
|
+
import {Code} from "#code";
|
|
1
2
|
import {combineCodes} from "../combine";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import type {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
import {makeFormat} from "../format";
|
|
4
|
+
|
|
5
|
+
import type {FormatContext} from "../context";
|
|
6
|
+
import type {Format, FormatBase} from "../format";
|
|
7
|
+
import type {ColorKey} from "./color";
|
|
8
|
+
|
|
9
|
+
const codes = (open: number) => ({
|
|
10
|
+
open : open as Code,
|
|
11
|
+
close : open + 9 as Code,
|
|
12
|
+
offset : (delta: number): Code => open + delta,
|
|
13
|
+
extended : (...args: number[]): Code => [open + 8, ...args],
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const baseCodes = {fg: codes(30), bg: codes(40)};
|
|
17
|
+
|
|
18
|
+
const disabledCodes: ReturnType<typeof codes> = {
|
|
19
|
+
open : Code.disabled,
|
|
20
|
+
close : Code.disabled,
|
|
21
|
+
offset : () => Code.disabled,
|
|
22
|
+
extended : () => Code.disabled,
|
|
9
23
|
};
|
|
10
24
|
|
|
11
|
-
export function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const {open, close} = baseCodes[channel];
|
|
19
|
-
|
|
20
|
-
const build = colorDepth > 1
|
|
21
|
-
? (open: Code): Format => makeFormatter(keys, open, close)
|
|
22
|
-
: () => makeFormatter(keys, [], []);
|
|
23
|
-
|
|
24
|
-
const combine = (base: FormatBase, style: FormatBase): Format => makeFormatter(
|
|
25
|
-
keys,
|
|
25
|
+
export function buildChannelContext(formatContext: FormatContext, channel: ColorKey) {
|
|
26
|
+
const {colorDepth} = formatContext.features;
|
|
27
|
+
const {open, close, extended, offset} = colorDepth > 1 ? baseCodes[channel] : disabledCodes;
|
|
28
|
+
|
|
29
|
+
const build = (open: Code): Format => makeFormat(formatContext, open, close);
|
|
30
|
+
const combine = (base: FormatBase, style: FormatBase): Format => makeFormat(
|
|
31
|
+
formatContext,
|
|
26
32
|
combineCodes(base.codes.open, style.codes.open),
|
|
27
33
|
combineCodes(base.codes.close, style.codes.close),
|
|
28
34
|
);
|
|
29
35
|
|
|
30
36
|
const bright: (index: number) => Format =
|
|
31
|
-
colorDepth >= 4 ? index => build(
|
|
37
|
+
colorDepth >= 4 ? index => build(offset(60 + index)) :
|
|
32
38
|
colorDepth === 3 ?
|
|
33
39
|
channel === "fg" ?
|
|
34
|
-
index => combine(style.bold, build(
|
|
35
|
-
index => build(
|
|
36
|
-
() => build(
|
|
40
|
+
index => combine(formatContext.style.bold, build(offset(index))) :
|
|
41
|
+
index => build(offset(index)) :
|
|
42
|
+
() => build(Code.disabled);
|
|
37
43
|
|
|
38
44
|
const x16ToX8: (code: number) => Format =
|
|
39
|
-
channel === "fg"
|
|
40
|
-
code => code >= 60 ?
|
|
41
|
-
code =>
|
|
45
|
+
channel === "fg"
|
|
46
|
+
? code => code >= 60 ? bright(code - 60) : build(offset(code))
|
|
47
|
+
: code => build(offset(code % 60));
|
|
42
48
|
|
|
43
|
-
return {colorDepth, channel, open, close, build, bright, x16ToX8};
|
|
49
|
+
return {colorDepth, channel, open, close, offset, extended, build, bright, x16ToX8};
|
|
44
50
|
}
|
|
45
51
|
|
|
46
|
-
export type
|
|
52
|
+
export type ChannelContext = ReturnType<typeof buildChannelContext>;
|
package/src/sgr/color/rgb.ts
CHANGED
|
@@ -1,35 +1,38 @@
|
|
|
1
|
+
import {Code} from "#code";
|
|
1
2
|
import {clip, rgbToX256, rgbToX16, rgbToX8, x256ToRgb} from "./utils";
|
|
2
3
|
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
4
|
+
import type {Format} from "../format";
|
|
5
|
+
import type {Channel} from "./channel";
|
|
6
|
+
import type {ChannelContext} from "./context";
|
|
5
7
|
|
|
6
|
-
export function makeRGB(ctx:
|
|
7
|
-
const {colorDepth, channel, build,
|
|
8
|
+
export function makeRGB(ctx: ChannelContext): Channel["rgb"] {
|
|
9
|
+
const {colorDepth, channel, build, offset, extended, x16ToX8} = ctx;
|
|
8
10
|
|
|
9
11
|
return (
|
|
10
|
-
colorDepth >= 24 ? (r, g, b) => build(
|
|
11
|
-
colorDepth >= 8 ? (r, g, b) => build(
|
|
12
|
-
colorDepth >= 4 ? (r, g, b) => build(
|
|
12
|
+
colorDepth >= 24 ? (r, g, b) => build(extended(2, ...clip(r, g, b))) :
|
|
13
|
+
colorDepth >= 8 ? (r, g, b) => build(extended(5, rgbToX256(...clip(r, g, b)))) :
|
|
14
|
+
colorDepth >= 4 ? (r, g, b) => build(offset(rgbToX16(...clip(r, g, b)))) :
|
|
13
15
|
colorDepth === 3 ?
|
|
14
16
|
channel === "fg" ?
|
|
15
17
|
(r, g, b) => x16ToX8(rgbToX16(...clip(r, g, b))) :
|
|
16
|
-
(r, g, b) => build(
|
|
17
|
-
() => build(
|
|
18
|
+
(r, g, b) => build(offset(rgbToX8(...clip(r, g, b)))) :
|
|
19
|
+
() => build(Code.disabled)
|
|
18
20
|
);
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
type X256 = (...args: [number] | [number, number, number]) => Format;
|
|
24
|
+
|
|
25
|
+
export function makeX256(ctx: ChannelContext): X256 {
|
|
26
|
+
const {colorDepth, channel, build, offset, extended, x16ToX8} = ctx;
|
|
23
27
|
|
|
24
28
|
return (
|
|
25
29
|
colorDepth >= 8 ?
|
|
26
30
|
(...args) => build(
|
|
27
|
-
|
|
31
|
+
extended(5, args.length === 3 ? rgbToX256(...clip(...args)) : clip(args[0])),
|
|
28
32
|
) :
|
|
29
33
|
colorDepth >= 4 ?
|
|
30
34
|
(...args) => build(
|
|
31
|
-
|
|
32
|
-
rgbToX16(...(args.length === 3 ? clip(...args) : x256ToRgb(clip(args[0])))),
|
|
35
|
+
offset(rgbToX16(...(args.length === 3 ? clip(...args) : x256ToRgb(clip(args[0]))))),
|
|
33
36
|
) :
|
|
34
37
|
colorDepth === 3 ?
|
|
35
38
|
channel === "fg" ?
|
|
@@ -38,11 +41,9 @@ export function makeX256(ctx: Context): (...args: [number] | [number, number, nu
|
|
|
38
41
|
rgbToX16(...clip(...args)) :
|
|
39
42
|
rgbToX16(...x256ToRgb(clip(args[0]))),
|
|
40
43
|
) :
|
|
41
|
-
(...args) => build(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
) :
|
|
46
|
-
() => build([])
|
|
44
|
+
(...args) => build(offset(rgbToX8(
|
|
45
|
+
...args.length === 3 ? clip(...args) : x256ToRgb(clip(args[0])),
|
|
46
|
+
))) :
|
|
47
|
+
() => build(Code.disabled)
|
|
47
48
|
);
|
|
48
49
|
}
|
package/src/sgr/combine.ts
CHANGED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {getFeatures} from "#features";
|
|
2
|
+
import {allKeys} from "./chain";
|
|
3
|
+
import {makeStyle} from "./style";
|
|
4
|
+
|
|
5
|
+
import type {Codes} from "#code";
|
|
6
|
+
import type {Features} from "#features";
|
|
7
|
+
import type {ChainKey} from "./chain";
|
|
8
|
+
import type {FormatBase} from "./format";
|
|
9
|
+
import type {Style} from "./style";
|
|
10
|
+
|
|
11
|
+
export interface FormatContext<Keys extends ChainKey = ChainKey> {
|
|
12
|
+
features : Features;
|
|
13
|
+
keys : ReadonlySet<Keys>;
|
|
14
|
+
parentCodes? : Codes;
|
|
15
|
+
style : Style;
|
|
16
|
+
removeKey : <Key extends Keys>(key: Key) => FormatContext<Exclude<Keys, Key>>;
|
|
17
|
+
registerFormat : (format: FormatBase) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function removeKey<Keys extends ChainKey, Key extends Keys>(
|
|
21
|
+
context : FormatContext<Keys>,
|
|
22
|
+
key : Key,
|
|
23
|
+
): FormatContext<Exclude<Keys, Key>> {
|
|
24
|
+
const keys = new Set(context.keys);
|
|
25
|
+
keys.delete(key);
|
|
26
|
+
return {...context, keys: keys as unknown as ReadonlySet<Exclude<Keys, Key>>};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const cache = new WeakMap<FormatBase, FormatContext<any>>();
|
|
30
|
+
|
|
31
|
+
export function getContext(format: FormatBase, features?: Features): FormatContext<any> {
|
|
32
|
+
let context = cache.get(format);
|
|
33
|
+
if (context)
|
|
34
|
+
return context;
|
|
35
|
+
|
|
36
|
+
features ??= getFeatures(format.open ? 24 : 1);
|
|
37
|
+
|
|
38
|
+
context = {
|
|
39
|
+
features,
|
|
40
|
+
keys : allKeys,
|
|
41
|
+
parentCodes : format.codes,
|
|
42
|
+
style : undefined as unknown as Style,
|
|
43
|
+
removeKey : key => removeKey(context!, key),
|
|
44
|
+
registerFormat : (format: FormatBase) => void cache.set(format, context!),
|
|
45
|
+
};
|
|
46
|
+
context.style = makeStyle(context);
|
|
47
|
+
|
|
48
|
+
cache.set(format, context);
|
|
49
|
+
return context;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function createContext<Keys extends ChainKey = ChainKey>(
|
|
53
|
+
features : Features,
|
|
54
|
+
parentCodes? : Codes,
|
|
55
|
+
keys? : ReadonlySet<Keys>,
|
|
56
|
+
): FormatContext<Keys> {
|
|
57
|
+
const context: FormatContext<Keys> = {
|
|
58
|
+
features,
|
|
59
|
+
keys : keys ?? allKeys as ReadonlySet<Keys>,
|
|
60
|
+
parentCodes,
|
|
61
|
+
style : undefined as unknown as Style,
|
|
62
|
+
removeKey : key => removeKey(context, key),
|
|
63
|
+
registerFormat : format => void cache.set(format, context),
|
|
64
|
+
};
|
|
65
|
+
context.style = makeStyle(keys ? {...context, keys: allKeys} : context);
|
|
66
|
+
|
|
67
|
+
return context;
|
|
68
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {Code} from "#code";
|
|
2
|
+
import {codeSequence, csi} from "#utils";
|
|
3
|
+
import {define} from "@peteanderson/props";
|
|
4
|
+
import {attachChain} from "./chain";
|
|
5
|
+
import {combineCodes} from "./combine";
|
|
6
|
+
|
|
7
|
+
import type {Codes} from "#code";
|
|
8
|
+
import type {Chain, ChainKey} from "./chain";
|
|
9
|
+
import type {FormatContext} from "./context";
|
|
10
|
+
|
|
11
|
+
export interface FormatBase {
|
|
12
|
+
(text: string): string;
|
|
13
|
+
|
|
14
|
+
open : string;
|
|
15
|
+
close : string;
|
|
16
|
+
codes : Codes;
|
|
17
|
+
combine : (...formats: [FormatBase, ...FormatBase[]]) => FormatBase;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ChainedFormat<Keys extends ChainKey = ChainKey> extends FormatBase {
|
|
21
|
+
and: Chain<Keys>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type Format<Keys extends ChainKey = ChainKey> =
|
|
25
|
+
[Keys] extends [never] ? FormatBase : ChainedFormat<Keys>;
|
|
26
|
+
|
|
27
|
+
export function makeFormat<Keys extends ChainKey = ChainKey>(
|
|
28
|
+
context : FormatContext<Keys>,
|
|
29
|
+
open : Code,
|
|
30
|
+
close : Code,
|
|
31
|
+
reset? : boolean,
|
|
32
|
+
): Format<Keys> {
|
|
33
|
+
if (context.parentCodes) {
|
|
34
|
+
open = combineCodes(context.parentCodes.open, open);
|
|
35
|
+
close = combineCodes(close, context.parentCodes.close);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const openCode = codeSequence(open);
|
|
39
|
+
const closeCode = codeSequence(close);
|
|
40
|
+
const openSequence = csi(open, "m");
|
|
41
|
+
const closeSequence = csi(close, "m");
|
|
42
|
+
const reopenCode = reset ? `${closeCode};${openCode}` : openCode;
|
|
43
|
+
|
|
44
|
+
const rxClose = new RegExp(
|
|
45
|
+
`(?<start>\\x1b\\[(?:\\d+;)*)${closeCode}(?<end>(?:;\\d+)*m)`,
|
|
46
|
+
"g"
|
|
47
|
+
);
|
|
48
|
+
const replace = `$<start>${reopenCode}$<end>`;
|
|
49
|
+
|
|
50
|
+
const format = attachChain(context, define(
|
|
51
|
+
openSequence
|
|
52
|
+
? (s: string) => s ? openSequence + s.replace(rxClose, replace) + closeSequence : s
|
|
53
|
+
: (s: string) => s,
|
|
54
|
+
{
|
|
55
|
+
open : {value: openSequence, enumerable: true},
|
|
56
|
+
close : {value: closeSequence, enumerable: true},
|
|
57
|
+
codes : {value: {open, close}, enumerable: true},
|
|
58
|
+
combine : {
|
|
59
|
+
value: (...formats: [FormatBase, ...FormatBase[]]) => makeFormat(
|
|
60
|
+
context,
|
|
61
|
+
combineCodes(open, ...formats.map(f => f.codes.open)),
|
|
62
|
+
combineCodes(close, ...formats.map(f => f.codes.close)),
|
|
63
|
+
reset,
|
|
64
|
+
),
|
|
65
|
+
enumerable: true,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
));
|
|
69
|
+
|
|
70
|
+
context.registerFormat(format);
|
|
71
|
+
return format;
|
|
72
|
+
};
|
package/src/sgr/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export
|
|
1
|
+
export {chain} from "./chain"; // This export must come first to avoid circular dependency issues.
|
|
2
|
+
export * from "./sgr";
|
|
2
3
|
|
|
3
|
-
export {
|
|
4
|
+
export type {AddChain, ChainKey} from "./chain";
|
|
5
|
+
export type {Format, FormatBase} from "./format";
|
package/src/sgr/reset.ts
CHANGED
package/src/sgr/sgr.ts
CHANGED
|
@@ -1,30 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {makeColor}
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {makeReset}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import type {
|
|
9
|
-
import type {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
inverse : undefined,
|
|
19
|
-
hidden : undefined,
|
|
20
|
-
strikethrough : undefined,
|
|
21
|
-
doubleUnderline : undefined,
|
|
22
|
-
frame : undefined,
|
|
23
|
-
encircle : undefined,
|
|
24
|
-
overline : undefined,
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const allKeys: ReadonlySet<ChainKey> = new Set(TypedObject.keys(keyMap));
|
|
1
|
+
import {Code} from "#code";
|
|
2
|
+
import {makeColor} from "./color";
|
|
3
|
+
import {createContext} from "./context";
|
|
4
|
+
import {makeFormat} from "./format";
|
|
5
|
+
import {makeReset} from "./reset";
|
|
6
|
+
|
|
7
|
+
import type {ColorDepth, Features} from "#features";
|
|
8
|
+
import type {ChainKey} from "./chain";
|
|
9
|
+
import type {Color} from "./color";
|
|
10
|
+
import type {Format} from "./format";
|
|
11
|
+
import type {Style} from "./style";
|
|
12
|
+
|
|
13
|
+
export interface SGR extends Color<ChainKey> {
|
|
14
|
+
style : Style;
|
|
15
|
+
plain : Format<ChainKey>;
|
|
16
|
+
reset : string;
|
|
17
|
+
}
|
|
28
18
|
|
|
29
19
|
const cache: Partial<Record<`${ColorDepth}.${boolean}`, SGR>> = {};
|
|
30
20
|
|
|
@@ -33,30 +23,12 @@ export function makeSGR(features: Features): SGR {
|
|
|
33
23
|
if (cache[cacheKey])
|
|
34
24
|
return cache[cacheKey];
|
|
35
25
|
|
|
36
|
-
const
|
|
37
|
-
const style = makeStyle(allKeys, makeFormat, features.style);
|
|
38
|
-
|
|
39
|
-
function makeChain<Keys extends ChainKey>(
|
|
40
|
-
keys : ReadonlySet<Keys>,
|
|
41
|
-
baseFormat : FormatBase,
|
|
42
|
-
): Chain<Keys> {
|
|
43
|
-
const makeChainedFormat: FormatBuilder = (keys, open, close, reset) => makeFormat(
|
|
44
|
-
keys,
|
|
45
|
-
combineCodes(baseFormat.codes.open, open),
|
|
46
|
-
combineCodes(baseFormat.codes.close, close),
|
|
47
|
-
reset,
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
...makeColor(keys, makeChainedFormat, style, features.colorDepth),
|
|
52
|
-
...makeStyle(keys, makeChainedFormat, features.style),
|
|
53
|
-
};
|
|
54
|
-
}
|
|
26
|
+
const context = createContext(features);
|
|
55
27
|
|
|
56
28
|
const rtn: SGR = {
|
|
57
|
-
...makeColor(
|
|
58
|
-
style,
|
|
59
|
-
plain : makeFormat(
|
|
29
|
+
...makeColor(context),
|
|
30
|
+
style : context.style,
|
|
31
|
+
plain : makeFormat(context, Code.disabled, Code.disabled),
|
|
60
32
|
reset : makeReset(features.colorDepth > 1 || features.style),
|
|
61
33
|
};
|
|
62
34
|
|