@soybeanjs/colord 0.0.1

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.
@@ -0,0 +1,112 @@
1
+ import { _ as ALPHA_PRECISION, a as mul3x3, c as round, g as OKLAB_M2_INV, h as OKLAB_M2, i as isPresent, m as OKLAB_M1_INV, n as clampHue, o as parseAlpha, p as OKLAB_M1, s as parseHue, t as clamp } from "../utils-BgIyY6bK.js";
2
+ import { n as clampRgb, o as rgbToLinearRgb, r as linearRgbToRgb, t as clampLinearRgb } from "../rgb-CfVJB1Bj.js";
3
+
4
+ //#region src/models/oklch.ts
5
+ const clampOklch = (oklch) => {
6
+ const { l, c, h, alpha } = oklch;
7
+ return {
8
+ l: clamp(l, 1e-4, 1),
9
+ c: clamp(c, 1e-4, .37),
10
+ h: clampHue(h),
11
+ alpha: clamp(alpha)
12
+ };
13
+ };
14
+ const roundOklch = (oklch) => {
15
+ const { l, c, h, alpha } = oklch;
16
+ return {
17
+ l: round(l, 3),
18
+ c: round(c, 3),
19
+ h: round(h, 3),
20
+ alpha: round(alpha, ALPHA_PRECISION)
21
+ };
22
+ };
23
+ const oklchToRgb = (oklch) => {
24
+ const { l, c, h, alpha } = oklch;
25
+ const hRad = h * Math.PI / 180;
26
+ const [r, g, b] = mul3x3(OKLAB_M1_INV, mul3x3(OKLAB_M2_INV, [
27
+ l,
28
+ c * Math.cos(hRad),
29
+ c * Math.sin(hRad)
30
+ ]).map((v) => v * v * v));
31
+ return clampRgb(linearRgbToRgb(clampLinearRgb({
32
+ r,
33
+ g,
34
+ b,
35
+ alpha
36
+ })));
37
+ };
38
+ const rgbToOklch = (rgb) => {
39
+ const lRgb = rgbToLinearRgb(rgb);
40
+ const [l, a, b] = mul3x3(OKLAB_M2, mul3x3(OKLAB_M1, [
41
+ lRgb.r,
42
+ lRgb.g,
43
+ lRgb.b
44
+ ]).map((v) => Math.cbrt(v)));
45
+ const chroma = Math.sqrt(a * a + b * b);
46
+ let hue;
47
+ if (chroma < 1e-4) hue = 0;
48
+ else {
49
+ hue = Math.atan2(b, a) * (180 / Math.PI);
50
+ if (hue < 0) hue += 360;
51
+ }
52
+ return clampOklch({
53
+ l,
54
+ c: chroma,
55
+ h: hue,
56
+ alpha: rgb.alpha
57
+ });
58
+ };
59
+ const parseOklch = ({ l, c, h, alpha = 1 }) => {
60
+ if (!isPresent(l) || !isPresent(c) || !isPresent(h)) return null;
61
+ return oklchToRgb(clampOklch({
62
+ l: Number(l),
63
+ c: Number(c),
64
+ h: Number(h),
65
+ alpha: Number(alpha)
66
+ }));
67
+ };
68
+ /**
69
+ * Parsing syntax: oklch(L c h [/ alpha])
70
+ * - L: <number|percentage>
71
+ * - c: <number>
72
+ * - h: <number>
73
+ * - alpha: <number|percentage>
74
+ */
75
+ const oklchMatcher = /^oklch\(\s*([+-]?[\d.]+)%?\s+([+-]?[\d.]+)\s+([+-]?[\d.]+)(deg|grad|rad|turn)?(?:\s*\/\s*([+-]?[\d.]+%?))?\s*\)$/i;
76
+ /**
77
+ * Parses a valid OKLCH CSS color function/string
78
+ * https://www.w3.org/TR/css-color-4/#specifying-oklch
79
+ * @param input
80
+ * @returns
81
+ */
82
+ const parseOklchString = (input) => {
83
+ const match = oklchMatcher.exec(input);
84
+ if (!match) return null;
85
+ const [_, L, c, h, unit, alpha] = match;
86
+ let l = Number.parseFloat(L);
87
+ if (L.endsWith("%")) l /= 100;
88
+ return oklchToRgb(clampOklch({
89
+ l,
90
+ c: Number.parseFloat(c),
91
+ h: parseHue(h, unit),
92
+ alpha: parseAlpha(alpha)
93
+ }));
94
+ };
95
+
96
+ //#endregion
97
+ //#region src/plugins/oklch.ts
98
+ /**
99
+ * A plugin adding support for OKLCH colorspace.
100
+ * https://bottosson.github.io/posts/oklab/
101
+ */
102
+ const oklchPlugin = (ColordClass, parsers) => {
103
+ ColordClass.prototype.toOklch = function toOklch() {
104
+ return roundOklch(rgbToOklch(this.rgb));
105
+ };
106
+ parsers.string.push([parseOklchString, "oklch"]);
107
+ parsers.object.push([parseOklch, "oklch"]);
108
+ };
109
+ var oklch_default = oklchPlugin;
110
+
111
+ //#endregion
112
+ export { oklch_default as default, oklchPlugin };
@@ -0,0 +1,17 @@
1
+ import { g as XyzColor } from "../colord-xpgrVWRV.js";
2
+ import { t as Plugin } from "../extend-DrPfn2Q1.js";
3
+
4
+ //#region src/plugins/xyz.d.ts
5
+ declare module '../colord' {
6
+ interface Colord {
7
+ toXyz(): XyzColor;
8
+ }
9
+ }
10
+ /**
11
+ * A plugin adding support for CIE XYZ colorspace.
12
+ * Wikipedia: https://en.wikipedia.org/wiki/CIE_1931_color_space
13
+ * Helpful article: https://www.sttmedia.com/colormodel-xyz
14
+ */
15
+ declare const xyzPlugin: Plugin;
16
+ //#endregion
17
+ export { xyzPlugin as default, xyzPlugin };
@@ -0,0 +1,20 @@
1
+ import "../utils-BgIyY6bK.js";
2
+ import "../rgb-CfVJB1Bj.js";
3
+ import { n as rgbToXyz, r as roundXyz, t as parseXyz } from "../xyz-MII3ndWO.js";
4
+
5
+ //#region src/plugins/xyz.ts
6
+ /**
7
+ * A plugin adding support for CIE XYZ colorspace.
8
+ * Wikipedia: https://en.wikipedia.org/wiki/CIE_1931_color_space
9
+ * Helpful article: https://www.sttmedia.com/colormodel-xyz
10
+ */
11
+ const xyzPlugin = (ColordClass, parsers) => {
12
+ ColordClass.prototype.toXyz = function toXyz() {
13
+ return roundXyz(rgbToXyz(this.rgb));
14
+ };
15
+ parsers.object.push([parseXyz, "xyz"]);
16
+ };
17
+ var xyz_default = xyzPlugin;
18
+
19
+ //#endregion
20
+ export { xyz_default as default, xyzPlugin };
@@ -0,0 +1,148 @@
1
+ import { _ as ALPHA_PRECISION, c as round, i as isPresent, o as parseAlpha, t as clamp } from "./utils-BgIyY6bK.js";
2
+
3
+ //#region src/models/rgb.ts
4
+ const clampRgb = (rgb) => {
5
+ const { r, g, b, alpha } = rgb;
6
+ return {
7
+ r: clamp(r, 0, 255),
8
+ g: clamp(g, 0, 255),
9
+ b: clamp(b, 0, 255),
10
+ alpha: clamp(alpha)
11
+ };
12
+ };
13
+ const roundRgb = (rgb) => {
14
+ const { r, g, b, alpha } = rgb;
15
+ return {
16
+ r: round(r),
17
+ g: round(g),
18
+ b: round(b),
19
+ alpha: round(alpha, ALPHA_PRECISION)
20
+ };
21
+ };
22
+ const clampLinearRgb = (rgb) => {
23
+ const { r, g, b, alpha } = rgb;
24
+ return {
25
+ r: clamp(r, 1e-4, 1),
26
+ g: clamp(g, 1e-4, 1),
27
+ b: clamp(b, 1e-4, 1),
28
+ alpha: clamp(alpha)
29
+ };
30
+ };
31
+ const parseRgb = ({ r, g, b, alpha = 1 }) => {
32
+ if (!isPresent(r) || !isPresent(g) || !isPresent(b)) return null;
33
+ return clampRgb({
34
+ r: Number(r),
35
+ g: Number(g),
36
+ b: Number(b),
37
+ alpha: Number(alpha)
38
+ });
39
+ };
40
+ /**
41
+ * Converts a single sRGB component value to linear light.
42
+ * This applies gamma expansion (inverse of sRGB transfer function).
43
+ *
44
+ * The sRGB transfer function has two parts:
45
+ * - Linear segment for very dark values (≤ 0.04045)
46
+ * - Power curve with gamma ≈ 2.4 for brighter values
47
+ *
48
+ * @param value - sRGB component value (0-255)
49
+ */
50
+ const rgbToLinear = (value) => {
51
+ const v = value / 255;
52
+ if (v <= .04045) return v / 12.92;
53
+ return ((v + .055) / 1.055) ** 2.4;
54
+ };
55
+ /**
56
+ * Converts a linear light value to sRGB component.
57
+ * This applies gamma compression (sRGB transfer function).
58
+ *
59
+ * The sRGB transfer function has two parts:
60
+ * - Linear segment for very dark values (≤ 0.0031308)
61
+ * - Power curve with gamma ≈ 1/2.4 for brighter values
62
+ *
63
+ * @param value - Linear light value (0-1)
64
+ */
65
+ function linearToRgb(value) {
66
+ const v = value <= .0031308 ? value * 12.92 : 1.055 * value ** (1 / 2.4) - .055;
67
+ return Math.round(v * 255);
68
+ }
69
+ /**
70
+ * Converts an RGBA color to Linear RGB color space.
71
+ *
72
+ * This applies gamma expansion to each RGB component,
73
+ * converting from perceptually uniform sRGB to physically
74
+ * linear light values. Alpha channel is passed through unchanged.
75
+ *
76
+ * @param rgb - The RGBA color to convert (r, g, b: 0-255, a: 0-1)
77
+ */
78
+ function rgbToLinearRgb(rgb) {
79
+ return {
80
+ r: rgbToLinear(rgb.r),
81
+ g: rgbToLinear(rgb.g),
82
+ b: rgbToLinear(rgb.b),
83
+ alpha: rgb.alpha
84
+ };
85
+ }
86
+ /**
87
+ * Converts a Linear RGB color to RGBA color space.
88
+ *
89
+ * This applies gamma compression to each RGB component,
90
+ * converting from physically linear light values to
91
+ * perceptually uniform sRGB. Alpha channel is passed through unchanged.
92
+ *
93
+ * @param rgb - The LinearRGB color to convert (r, g, b: 0-1 linear, a: 0-1)
94
+ * @returns RGBA color (r, g, b: 0-255, a: 0-1)
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * // Pure red
99
+ * linearRgbToRgb({ r: 1, g: 0, b: 0, a: 1 });
100
+ * // { r: 255, g: 0, b: 0, a: 1 }
101
+ *
102
+ * // Linear mid-point is NOT perceptual mid-gray
103
+ * linearRgbToRgb({ r: 0.5, g: 0.5, b: 0.5, a: 1 });
104
+ * // { r: 188, g: 188, b: 188, a: 1 } - looks quite bright!
105
+ *
106
+ * // With transparency
107
+ * linearRgbToRgb({ r: 1, g: 0.216, b: 0, a: 0.5 });
108
+ * // { r: 255, g: 128, b: 0, a: 0.5 }
109
+ * ```
110
+ */
111
+ function linearRgbToRgb(rgb) {
112
+ return {
113
+ r: linearToRgb(rgb.r),
114
+ g: linearToRgb(rgb.g),
115
+ b: linearToRgb(rgb.b),
116
+ alpha: rgb.alpha
117
+ };
118
+ }
119
+ const rgbMatcher = /^rgb?\(\s*([\d.]+%?)\s*[, ]\s*([\d.]+%?)\s*[, ]\s*([\d.]+%?)(?:\s*[,/]\s*([\d.]+%?))?\s*\)$/i;
120
+ /**
121
+ * Parses a valid RGB[A] CSS color function/string
122
+ * https://www.w3.org/TR/css-color-4/#rgb-functions
123
+ */
124
+ const parseRgbString = (input) => {
125
+ const match = rgbMatcher.exec(input);
126
+ if (!match) return null;
127
+ const [_, r, g, b, alpha] = match;
128
+ return clampRgb({
129
+ r: parseValue(r),
130
+ g: parseValue(g),
131
+ b: parseValue(b),
132
+ alpha: parseAlpha(alpha)
133
+ });
134
+ };
135
+ function parseValue(str) {
136
+ if (str.endsWith("%")) {
137
+ const percent = Number.parseFloat(str.slice(0, -1));
138
+ return Math.round(percent / 100 * 255);
139
+ }
140
+ return Number.parseFloat(str);
141
+ }
142
+ const rgbToRgbString = (rgb) => {
143
+ const { r, g, b, alpha } = roundRgb(rgb);
144
+ return alpha < 1 ? `rgb(${r}, ${g}, ${b}, ${alpha})` : `rgb(${r}, ${g}, ${b})`;
145
+ };
146
+
147
+ //#endregion
148
+ export { parseRgbString as a, roundRgb as c, parseRgb as i, clampRgb as n, rgbToLinearRgb as o, linearRgbToRgb as r, rgbToRgbString as s, clampLinearRgb as t };
@@ -0,0 +1,229 @@
1
+ //#region src/constants/common.ts
2
+ /**
3
+ * We used to work with 2 digits after the decimal point, but it wasn't accurate enough,
4
+ * so the library produced colors that were perceived differently.
5
+ */
6
+ const ALPHA_PRECISION = 3;
7
+ /**
8
+ * Valid CSS <angle> units.
9
+ * https://developer.mozilla.org/en-US/docs/Web/CSS/angle
10
+ */
11
+ const ANGLE_UNITS = {
12
+ grad: 360 / 400,
13
+ turn: 360,
14
+ rad: 360 / (Math.PI * 2)
15
+ };
16
+ const D50 = {
17
+ x: .96422,
18
+ y: 1,
19
+ z: .82521
20
+ };
21
+
22
+ //#endregion
23
+ //#region src/constants/matrix.ts
24
+ const OKLAB_M1 = [
25
+ [
26
+ .4122214708,
27
+ .5363325363,
28
+ .0514459929
29
+ ],
30
+ [
31
+ .2119034982,
32
+ .6806995451,
33
+ .1073969566
34
+ ],
35
+ [
36
+ .0883024619,
37
+ .2817188376,
38
+ .6299787005
39
+ ]
40
+ ];
41
+ const OKLAB_M1_INV = [
42
+ [
43
+ 4.076741661347993,
44
+ -3.3077115904081937,
45
+ .2309699287294278
46
+ ],
47
+ [
48
+ -1.2684380040921763,
49
+ 2.609757400663372,
50
+ -.3413193963102196
51
+ ],
52
+ [
53
+ -.0041960865418371,
54
+ -.7034186144594495,
55
+ 1.7076147009309446
56
+ ]
57
+ ];
58
+ const OKLAB_M2 = [
59
+ [
60
+ .2104542553,
61
+ .793617785,
62
+ -.0040720468
63
+ ],
64
+ [
65
+ 1.9779984951,
66
+ -2.428592205,
67
+ .4505937099
68
+ ],
69
+ [
70
+ .0259040371,
71
+ .7827717662,
72
+ -.808675766
73
+ ]
74
+ ];
75
+ const OKLAB_M2_INV = [
76
+ [
77
+ .9999999984505198,
78
+ .3963377921737678,
79
+ .2158037580607588
80
+ ],
81
+ [
82
+ 1.0000000088817607,
83
+ -.1055613423236563,
84
+ -.0638541747717059
85
+ ],
86
+ [
87
+ 1.0000000546724108,
88
+ -.0894841820949657,
89
+ -1.2914855378640917
90
+ ]
91
+ ];
92
+ const M_SRGB_TO_XYZ_D65 = [
93
+ [
94
+ .4124564391,
95
+ .3575760776,
96
+ .1804374833
97
+ ],
98
+ [
99
+ .2126728514,
100
+ .7151521552,
101
+ .0721749934
102
+ ],
103
+ [
104
+ .0193338956,
105
+ .1191920259,
106
+ .9503040785
107
+ ]
108
+ ];
109
+ const M_XYZ_D65_TO_SRGB = [
110
+ [
111
+ 3.2404541621,
112
+ -1.5371385127,
113
+ -.4985314095
114
+ ],
115
+ [
116
+ -.9692660305,
117
+ 1.8760108454,
118
+ .0415560175
119
+ ],
120
+ [
121
+ .055643431,
122
+ -.2040259135,
123
+ 1.0572251882
124
+ ]
125
+ ];
126
+ const M_D65_TO_D50 = [
127
+ [
128
+ 1.0478112,
129
+ .0228866,
130
+ -.050127
131
+ ],
132
+ [
133
+ .0295424,
134
+ .9904844,
135
+ -.0170491
136
+ ],
137
+ [
138
+ -.0092345,
139
+ .0150436,
140
+ .7521316
141
+ ]
142
+ ];
143
+ const M_D50_TO_D65 = [
144
+ [
145
+ .9555766,
146
+ -.0230393,
147
+ .0631636
148
+ ],
149
+ [
150
+ -.0282895,
151
+ 1.0099416,
152
+ .0210077
153
+ ],
154
+ [
155
+ .0122982,
156
+ -.020483,
157
+ 1.3299098
158
+ ]
159
+ ];
160
+
161
+ //#endregion
162
+ //#region src/utils/index.ts
163
+ const isPresent = (value) => {
164
+ if (typeof value === "string") return value.length > 0;
165
+ if (typeof value === "number") return true;
166
+ return false;
167
+ };
168
+ /**
169
+ * Rounds a number to the specified number of decimal places.
170
+ * @param number - The number to round
171
+ * @param digits - The number of decimal places (default: 0)
172
+ * @returns The rounded number (converts -0 to 0)
173
+ */
174
+ const round = (number, digits = 0) => {
175
+ const base = 10 ** digits;
176
+ return Math.round(base * number) / base + 0;
177
+ };
178
+ /**
179
+ * Floors a number to the specified number of decimal places.
180
+ * @param number - The number to floor
181
+ * @param digits - The number of decimal places (default: 0)
182
+ * @returns The floored number (converts -0 to 0)
183
+ */
184
+ const floor = (number, digits = 0) => {
185
+ const base = 10 ** digits;
186
+ return Math.floor(base * number) / base + 0;
187
+ };
188
+ /**
189
+ * Clamps a value between an upper and lower bound.
190
+ * We use ternary operators because it makes the minified code
191
+ * is 2 times shorter then `Math.min(Math.max(a,b),c)`
192
+ * NaN is clamped to the lower bound
193
+ */
194
+ const clamp = (number, min = 0, max = 1) => {
195
+ if (number > max) return max;
196
+ if (number < min) return min;
197
+ return number;
198
+ };
199
+ /**
200
+ * Processes and clamps a degree (angle) value properly.
201
+ * Any `NaN` or `Infinity` will be converted to `0`.
202
+ * Examples: -1 => 359, 361 => 1
203
+ */
204
+ const clampHue = (degrees) => {
205
+ const degree = Number.isFinite(degrees) ? degrees % 360 : 0;
206
+ return degree > 0 ? degree : degree + 360;
207
+ };
208
+ /**
209
+ * Converts a hue value to degrees from 0 to 360 inclusive.
210
+ */
211
+ const parseHue = (value, unit = "deg") => {
212
+ return Number.parseFloat(value) * (ANGLE_UNITS[unit] || 1);
213
+ };
214
+ function mul3x3(m, v) {
215
+ return [
216
+ m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2],
217
+ m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2],
218
+ m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2]
219
+ ];
220
+ }
221
+ function parseAlpha(alpha) {
222
+ if (!alpha) return 1;
223
+ let value = Number.parseFloat(alpha);
224
+ if (alpha.endsWith("%")) value /= 100;
225
+ return value;
226
+ }
227
+
228
+ //#endregion
229
+ export { ALPHA_PRECISION as _, mul3x3 as a, round as c, M_SRGB_TO_XYZ_D65 as d, M_XYZ_D65_TO_SRGB as f, OKLAB_M2_INV as g, OKLAB_M2 as h, isPresent as i, M_D50_TO_D65 as l, OKLAB_M1_INV as m, clampHue as n, parseAlpha as o, OKLAB_M1 as p, floor as r, parseHue as s, clamp as t, M_D65_TO_D50 as u, D50 as v };
@@ -0,0 +1,73 @@
1
+ import { _ as ALPHA_PRECISION, a as mul3x3, c as round, d as M_SRGB_TO_XYZ_D65, f as M_XYZ_D65_TO_SRGB, i as isPresent, t as clamp, v as D50 } from "./utils-BgIyY6bK.js";
2
+ import { n as clampRgb, o as rgbToLinearRgb, r as linearRgbToRgb } from "./rgb-CfVJB1Bj.js";
3
+
4
+ //#region src/models/xyz.ts
5
+ /**
6
+ * Limits XYZ axis values assuming XYZ is relative to D50.
7
+ */
8
+ const clampXyz = (xyz) => {
9
+ const { x, y, z, alpha } = xyz;
10
+ return {
11
+ x: clamp(x, 1e-4, D50.x),
12
+ y: clamp(y, 1e-4, D50.y),
13
+ z: clamp(z, 1e-4, D50.z),
14
+ alpha: clamp(alpha)
15
+ };
16
+ };
17
+ const roundXyz = (xyz) => {
18
+ const { x, y, z, alpha } = xyz;
19
+ return {
20
+ x: round(x, 4),
21
+ y: round(y, 4),
22
+ z: round(z, 4),
23
+ alpha: round(alpha, ALPHA_PRECISION)
24
+ };
25
+ };
26
+ /**
27
+ * Converts an CIE XYZ color (D50) to RGBA color space (D65)
28
+ * https://www.w3.org/TR/css-color-4/#color-conversion-code
29
+ */
30
+ const xyzToRgb = (xyz) => {
31
+ const { x, y, z, alpha } = xyz;
32
+ const [r, g, b] = mul3x3(M_XYZ_D65_TO_SRGB, [
33
+ x,
34
+ y,
35
+ z
36
+ ]);
37
+ return clampRgb(linearRgbToRgb({
38
+ r,
39
+ g,
40
+ b,
41
+ alpha
42
+ }));
43
+ };
44
+ /**
45
+ * Converts an RGB color (D65) to CIE XYZ (D50)
46
+ * https://image-engineering.de/library/technotes/958-how-to-convert-between-srgb-and-ciexyz
47
+ */
48
+ const rgbToXyz = (rgb) => {
49
+ const { r, g, b, alpha } = rgbToLinearRgb(rgb);
50
+ const [x, y, z] = mul3x3(M_SRGB_TO_XYZ_D65, [
51
+ r,
52
+ g,
53
+ b
54
+ ]);
55
+ return clampXyz({
56
+ x,
57
+ y,
58
+ z,
59
+ alpha
60
+ });
61
+ };
62
+ const parseXyz = ({ x, y, z, alpha = 1 }) => {
63
+ if (!isPresent(x) || !isPresent(y) || !isPresent(z)) return null;
64
+ return xyzToRgb(clampXyz({
65
+ x: Number(x),
66
+ y: Number(y),
67
+ z: Number(z),
68
+ alpha: Number(alpha)
69
+ }));
70
+ };
71
+
72
+ //#endregion
73
+ export { xyzToRgb as i, rgbToXyz as n, roundXyz as r, parseXyz as t };
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "@soybeanjs/colord",
3
+ "type": "module",
4
+ "version": "0.0.1",
5
+ "description": "A tiny yet powerful tool for high-performance color manipulations and conversions",
6
+ "author": {
7
+ "name": "Soybean",
8
+ "email": "soybeanjs@outlook.com",
9
+ "url": "https://github.com/soybeanjs"
10
+ },
11
+ "license": "MIT",
12
+ "homepage": "https://github.com/soybeanjs/colord",
13
+ "repository": {
14
+ "url": "https://github.com/soybeanjs/colord.git"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/soybeanjs/colord/issues"
18
+ },
19
+ "publishConfig": {
20
+ "registry": "https://registry.npmjs.org/"
21
+ },
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js",
26
+ "require": "./dist/index.js"
27
+ },
28
+ "./plugins/*": {
29
+ "types": "./dist/plugins/*.d.ts",
30
+ "import": "./dist/plugins/*.js",
31
+ "require": "./dist/plugins/*.js"
32
+ }
33
+ },
34
+ "main": "./dist/index.js",
35
+ "module": "./dist/index.js",
36
+ "types": "./dist/index.d.ts",
37
+ "files": [
38
+ "dist"
39
+ ],
40
+ "dependencies": {
41
+ "cli-progress": "3.12.0",
42
+ "consola": "3.4.2",
43
+ "dayjs": "1.11.19",
44
+ "execa": "9.6.1",
45
+ "kolorist": "1.8.0",
46
+ "ofetch": "1.5.1"
47
+ },
48
+ "devDependencies": {
49
+ "@soybeanjs/cli": "1.4.4",
50
+ "@soybeanjs/eslint-config": "1.7.5",
51
+ "@types/cli-progress": "3.11.6",
52
+ "@types/node": "25.0.8",
53
+ "@types/tinycolor2": "^1.4.6",
54
+ "colord": "^2.9.3",
55
+ "eslint": "9.39.2",
56
+ "lint-staged": "16.2.7",
57
+ "simple-git-hooks": "2.13.1",
58
+ "tinycolor2": "^1.6.0",
59
+ "tsdown": "0.19.0",
60
+ "tsx": "4.21.0",
61
+ "typescript": "5.9.3"
62
+ },
63
+ "simple-git-hooks": {
64
+ "commit-msg": "pnpm soy git-commit-verify",
65
+ "pre-commit": "pnpm typecheck && pnpm lint-staged"
66
+ },
67
+ "lint-staged": {
68
+ "*": "eslint --fix"
69
+ },
70
+ "scripts": {
71
+ "build": "tsdown",
72
+ "cleanup": "soy cleanup",
73
+ "commit": "soy git-commit",
74
+ "dev": "tsup --watch",
75
+ "lint": "eslint . --fix",
76
+ "publish-pkg": "pnpm publish --access public",
77
+ "release": "soy release",
78
+ "typecheck": "tsc --noEmit --skipLibCheck",
79
+ "update-pkg": "soy ncu"
80
+ }
81
+ }