Skip to content

Commit e000014

Browse files
committed
Add color (hex, rgb, and hsl) string formats
1 parent 825e4df commit e000014

File tree

5 files changed

+124
-29
lines changed

5 files changed

+124
-29
lines changed

README.md

+31-28
Original file line numberDiff line numberDiff line change
@@ -247,34 +247,37 @@ The following table illustrates the results of different email strings
247247

248248
The following table illustrates the rest of the formats JSON Infer Types supports
249249

250-
| Example Strings | Name | Variant |
251-
| ----------------------------------------- | ----------- | --------- |
252-
| `"USD"`, `"BTC"` | currency | iso4217 |
253-
| `"United States dollar"`, `"Euro"` | currency | english |
254-
| `"ETH"`, `"LTC"` | currency | crypto |
255-
| `'$'`, `'£'`, `'€'`, `'¥'` | currency | symbol |
256-
| `"USA"`, `"MMR"` | country | iso3166-3 |
257-
| `"US"`, `"GB"`, `"JP"` | country | iso3166-2 |
258-
| `".com"`, `".co.uk"`, `".biz"` | tld | |
259-
| `"192.168.0.1"`, `"172.16.0.0"` | ip | v4 |
260-
| `"2001:db8:1234::1"` | ip | v6 |
261-
| `"en"`, `"ab"`, `"es"` | language | iso693-1 |
262-
| `"eng"`, `"eus"`, `"zul"` | language | iso693-2 |
263-
| `"Arabic"`, `"Welsh"`, `"Russian"` | language | english |
264-
| `"dansk"`, `"Español"` | language | native |
265-
| `"+1 (684) 633-5115"`, `"+49 30 83050"` | phoneNumber | e.164 |
266-
| `"4677658f-8865-47db-afb0-908e25246348"` | uuid | v4 |
267-
| `"cfa649f0-650b-11ec-acb3-03462fc79f5d"` | uuid | v1 |
268-
| `"bde4a7b9-5793-5a1f-b378-211205b15898"` | uuid | v5 |
269-
| `"foo.example.com"`, `"localhost"` | hostname | rfc1123 |
270-
| `"exa_mple.com"` | hostname | rfc5890 |
271-
| `"544B"`, `"1.0MB"`, `"377K"`, `"1.87GB"` | filesize | human |
272-
| `'{ "foo": 1 }'` | json | ecma262 |
273-
| `'{ foo: 1, }'` | json | json5 |
274-
| `"/foo/bar"`, `"/foo/-/bar"` | jsonPointer | rfc6901 |
275-
| `"0/foo/bar"`, `"2/0/baz/1/zip"` | jsonPointer | relative |
276-
| `"😄"`, `"🤪👨🏽‍🚀"`, `"👩‍👩‍👧‍👧"` | emoji | |
277-
| `"1.11.0"`, `"0.0.1"`, `"1.0.0-alpha.1"` | semver | |
250+
| Example Strings | Name | Variant |
251+
| ---------------------------------------------------- | ----------- | --------- |
252+
| `"USD"`, `"BTC"` | currency | iso4217 |
253+
| `"United States dollar"`, `"Euro"` | currency | english |
254+
| `"ETH"`, `"LTC"` | currency | crypto |
255+
| `'$'`, `'£'`, `'€'`, `'¥'` | currency | symbol |
256+
| `"USA"`, `"MMR"` | country | iso3166-3 |
257+
| `"US"`, `"GB"`, `"JP"` | country | iso3166-2 |
258+
| `".com"`, `".co.uk"`, `".biz"` | tld | |
259+
| `"192.168.0.1"`, `"172.16.0.0"` | ip | v4 |
260+
| `"2001:db8:1234::1"` | ip | v6 |
261+
| `"en"`, `"ab"`, `"es"` | language | iso693-1 |
262+
| `"eng"`, `"eus"`, `"zul"` | language | iso693-2 |
263+
| `"Arabic"`, `"Welsh"`, `"Russian"` | language | english |
264+
| `"dansk"`, `"Español"` | language | native |
265+
| `"+1 (684) 633-5115"`, `"+49 30 83050"` | phoneNumber | e.164 |
266+
| `"4677658f-8865-47db-afb0-908e25246348"` | uuid | v4 |
267+
| `"cfa649f0-650b-11ec-acb3-03462fc79f5d"` | uuid | v1 |
268+
| `"bde4a7b9-5793-5a1f-b378-211205b15898"` | uuid | v5 |
269+
| `"foo.example.com"`, `"localhost"` | hostname | rfc1123 |
270+
| `"exa_mple.com"` | hostname | rfc5890 |
271+
| `"544B"`, `"1.0MB"`, `"377K"`, `"1.87GB"` | filesize | human |
272+
| `'{ "foo": 1 }'` | json | ecma262 |
273+
| `'{ foo: 1, }'` | json | json5 |
274+
| `"/foo/bar"`, `"/foo/-/bar"` | jsonPointer | rfc6901 |
275+
| `"0/foo/bar"`, `"2/0/baz/1/zip"` | jsonPointer | relative |
276+
| `"😄"`, `"🤪👨🏽‍🚀"`, `"👩‍👩‍👧‍👧"` | emoji | |
277+
| `"1.11.0"`, `"0.0.1"`, `"1.0.0-alpha.1"` | semver | |
278+
| `"#ff0000"`, `"#D47DB9"` | color | hex |
279+
| `"rgb(255, 255, 255)"`, `"rgb(255, 255, 255,.5)"` | color | rgb |
280+
| `"hsl(100, 100%, 50%)"`, `"hsl(235, 100%, 50%, .5)"` | color | hsl |
278281

279282
## Object Formats
280283

examples.json

+3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
"json5": "{foo:1,}",
4343
"jsonPointer": "/foo/bar",
4444
"emoji": "🤔",
45+
"colorHex": "#ff0000",
46+
"colorHsl": "hsl(0, 100%, 50%)",
47+
"colorRgb": "rgb(255, 0, 0)",
4548
"semver": "1.2.3",
4649
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.sruoLZNJ59anK67z25t80L62OXDerSiAhWerW-usZLQ"
4750
},

src/formats/color.ts

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
export type JSONColorFormat = {
2+
name: "color";
3+
variant: "hex" | "rgb" | "hsl";
4+
};
5+
6+
const hexRegex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;
7+
const rgbRegex =
8+
/^rgba?\((\d{1,3})(,|\s+)\s*(\d{1,3})(,|\s+)\s*(\d{1,3})(,\s*0?.\d{1,3})?(\s+\/\s+0?.\d{1,3})?\)$/;
9+
10+
const hslRegex =
11+
/^hsla?\((\d{1,3})(,|\s+)\s*(\d{1,3}%)(,|\s+)\s*(\d{1,3}%)(,\s*0?.\d{1,3})?(\s+\/\s+0?.\d{1,3})?\)$/;
12+
13+
export function inferColor(value: string): JSONColorFormat | undefined {
14+
if (hexRegex.test(value)) {
15+
return {
16+
name: "color",
17+
variant: "hex",
18+
};
19+
}
20+
21+
if (rgbRegex.test(value)) {
22+
return {
23+
name: "color",
24+
variant: "rgb",
25+
};
26+
}
27+
28+
if (hslRegex.test(value)) {
29+
return {
30+
name: "color",
31+
variant: "hsl",
32+
};
33+
}
34+
35+
return undefined;
36+
}

src/formats/index.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { inferEmoji, JSONEmojiFormat } from "./emoji";
1818
import { inferSemver, JSONSemverFormat } from "./semver";
1919
import { inferFirestoreTimestamp, JSONFirestoreTimestampFormat } from "./firestoreTimestamp";
2020
import { inferJWT, JSONJWTStringFormat } from "./jwt";
21+
import { inferColor, JSONColorFormat } from "./color";
2122

2223
export {
2324
JSONHostnameFormat,
@@ -38,6 +39,7 @@ export {
3839
JSONEmojiFormat,
3940
JSONSemverFormat,
4041
JSONJWTStringFormat,
42+
JSONColorFormat,
4143
};
4244

4345
export type JSONStringFormat =
@@ -58,7 +60,8 @@ export type JSONStringFormat =
5860
| JSONJSONPointerFormat
5961
| JSONEmojiFormat
6062
| JSONSemverFormat
61-
| JSONJWTStringFormat;
63+
| JSONJWTStringFormat
64+
| JSONColorFormat;
6265

6366
const formats = [
6467
inferDatetime,
@@ -79,6 +82,7 @@ const formats = [
7982
inferEmoji,
8083
inferSemver,
8184
inferJWT,
85+
inferColor,
8286
];
8387

8488
export function inferFormat(value: string): JSONStringFormat | undefined {

tests/stringFormats.test.ts

+49
Original file line numberDiff line numberDiff line change
@@ -624,3 +624,52 @@ describe("jwt", () => {
624624
});
625625
});
626626
});
627+
628+
describe("colors", () => {
629+
test.each(["#D47DB9", "#14C3FF", "#ff9933", "#fff"])(
630+
"%p should be inferred as a color hex",
631+
(value) => {
632+
expect(inferType(value)).toEqual({
633+
name: "string",
634+
value,
635+
format: {
636+
name: "color",
637+
variant: "hex",
638+
},
639+
});
640+
},
641+
);
642+
643+
test.each([
644+
"rgb(255, 255, 255)",
645+
"rgb(255, 255, 255,.5)",
646+
"rgba(255, 255, 255,.5)",
647+
"rgb(255 255 255)",
648+
"rgb(255 255 255 / .5)",
649+
])("%p should be inferred as a color rgb", (value) => {
650+
expect(inferType(value)).toEqual({
651+
name: "string",
652+
value,
653+
format: {
654+
name: "color",
655+
variant: "rgb",
656+
},
657+
});
658+
});
659+
660+
test.each([
661+
"hsl(100, 100%, 50%)",
662+
"hsl(235, 100%, 50%, .5)",
663+
"hsl(235 100% 50%)",
664+
"hsl(235 100% 50% / .5)",
665+
])("%p should be inferred as a color rgb", (value) => {
666+
expect(inferType(value)).toEqual({
667+
name: "string",
668+
value,
669+
format: {
670+
name: "color",
671+
variant: "hsl",
672+
},
673+
});
674+
});
675+
});

0 commit comments

Comments
 (0)