forked from catppuccin/userstyles
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.ts
More file actions
70 lines (63 loc) 路 2.54 KB
/
Copy pathutils.ts
File metadata and controls
70 lines (63 loc) 路 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import Ajv, { Schema } from "ajv";
import { parse } from "std/yaml/parse.ts";
import { join } from "std/path/join.ts";
import { SetRequired } from "type-fest/source/set-required.d.ts";
import { REPO_ROOT, userStylesSchema } from "@/deps.ts";
import { UserstylesSchema } from "@/types/userstyles.d.ts";
/**
* @param content A string of YAML content
* @param schema A JSON schema
* @returns A promise that resolves to the parsed YAML content, verified against the schema. Rejects if the content is invalid.
*/
export const validateYaml = <T>(
content: string,
schema: Schema,
): Promise<T> => {
return new Promise((resolve, reject) => {
const ajv = new Ajv.default();
const validate = ajv.compile<T>(schema);
const data = parse(content);
if (!validate(data)) return reject(validate.errors);
return resolve(data);
});
};
/**
* Utility function that calls {@link validateYaml} on the userstyles.yml file.
* Fails when data.userstyles is undefined.
*/
export const getUserstylesData = (): Promise<Userstyles> => {
return new Promise((resolve, reject) => {
validateYaml<UserstylesSchema>(
Deno.readTextFileSync(join(REPO_ROOT, "scripts/userstyles.yml")),
userStylesSchema,
).then((data) => {
if (data.userstyles === undefined || data.collaborators === undefined) {
return reject("userstyles.yml is missing required fields");
}
return resolve(data as Userstyles);
});
});
};
/**
* Utility function that formats a list of items into the "x, y, ..., and z" format.
* @example
* formatListOfItems(['x']); // 'x'
* @example
* formatListOfItems(['x', 'y']); // 'x and y'
* @example
* formatListOfItems(['x', 'y', 'z']); // 'x, y, and z'
*/
export const formatListOfItems = (items: unknown[]): string => {
// If there are two items, connect them with an "and".
if (items.length === 2) return items.join(" and ");
// Otherwise, there is either just one item or more than two items.
return items.reduce((prev, curr, idx, arr) => {
// If this is the first item of the items we are looping through, set our initial string to it.
if (idx === 0) return curr;
// If this is the last one, add a comma (Oxford commas are amazing) followed by "and" and the item to the string.
if (curr === arr.at(-1)) return prev + `, and ${curr}`;
// Otherwise, it is some item in the middle of the list and we can just add it as a comma followed by the item to the string.
return prev + `, ${curr}`;
}) as string;
};
type Userstyles = SetRequired<UserstylesSchema, "userstyles" | "collaborators">;