-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathcreate-hidive-member.ts
136 lines (127 loc) · 3.86 KB
/
create-hidive-member.ts
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/**
* @module Creates a markdown file for a new member for the lab website.
*
* This script is intended to be used in conjunction with GitHub Actions.
*
* It reads a JSON file with the following structure:
*
* ```json
* {
* "slug": "jane-doe",
* "name": "Jane Doe",
* "degree": "PhD",
* "image": "<img src=\"https://github.com/user-attachments/assets/32f4b95c-7d2f-452e-85f5-c0351328023d\">",
* "image_alt": "alt text for the image..",
* "job_title": "Postdoctoral Researcher",
* "role": "postdoc",
* "social_media": "linked-in | https://www.linkedin.com/in/jane-doe\ngithub | https://github.com/foo",
* "start_date": "October 2021",
* "biography": "Jane Doe is a postdoctoral researcher..."
* }
* ```
*
* @example
* ```sh
* deno run -A scripts/create-hidive-member.ts paper.json
* ```
*/
import * as yaml from "jsr:@std/[email protected]";
import { z } from "npm:[email protected]";
import * as util from "./util.ts";
type Member = z.infer<typeof issueTemplateSchema>;
let issueTemplateSchema = z.object({
slug: z.string()
.transform((x) => x.trim())
.transform((x) => x.endsWith(".md") ? x.slice(0, -3) : x),
name: z.string().transform((x) => x.trim()),
degree: z.string().nullable().transform((x) => x?.trim()),
image: z.string()
.nullable()
.transform(util.parseImageMarkdown),
image_alt: z.string()
.nullable()
.transform((x) => x?.trim())
.transform((x) => x === "" ? undefined : x),
job_title: z.string().transform((x) => x.trim()),
role: z.string().transform((x) => x.trim()),
social_media: z
.string()
.nullable()
.transform((x) =>
x?.split("\n").map((y) => {
let [title, url] = y
.trim()
.split("|")
.filter((z) => z)
.map((z) => z.trim());
return { title, url };
})
),
start_date: z.string().transform((x) => x.trim()),
biography: z.string().transform((x) => x.trim()),
});
/**
* Convert a News object to a lab news markdown file.
*
* See `_news/` for examples.
*
* @param news The news object
* @returns The markdown content
*/
function toMarkdown({ biography, ...m }: Member): string {
// lab member frontmatter
let frontmatter: {
title: string;
name_degree: string;
photo: string;
alt: string;
job_title: string;
role: string;
services: Array<string>;
start: string;
end: string | null;
} = {
title: m.name,
name_degree: m.degree ? `${m.name}, ${m.degree}` : m.name,
photo: m.image.src ?? "<TODO>",
alt: m.image_alt ?? m.name,
job_title: m.job_title,
role: m.role,
services: m.social_media?.map((x) => `${x.title}: ${x.url}`) ?? [],
start: m.start_date,
end: null,
};
let fm = yaml.stringify(frontmatter, { lineWidth: 120 });
let body = biography.trim();
// ensure there is a newline at the end
return `---\n${fm}---\n${body}${body.endsWith("\n") ? "" : "\n"}`;
}
if (import.meta.main) {
let json = await util.readJson(Deno.args[0]);
let issue = issueTemplateSchema.parse(json);
if (issue.image.src) {
let resp = await fetch(issue.image.src);
let type = resp.headers.get("content-type");
if (!resp.ok || !type) {
console.error(`Failed to fetch image: ${issue.image.src}`);
} else {
let fname = `${issue.slug}.${type.split("/")[1]}`;
await util.downloadImageResponse(resp, {
to: new URL(
`../assets/img/members/fullsize/${fname}`,
import.meta.url,
),
});
issue.image.src = fname;
}
}
await Deno.writeTextFile(
new URL(`../_members/${issue.slug}.md`, import.meta.url),
toMarkdown(issue),
);
Deno.stdout.write(new TextEncoder().encode(`\
This is an automated PR adding a new announcement to the lab website.
> ${issue.name} joined the lab as a ${issue.job_title} in ${issue.start_date}.
Please review the changes and merge the PR if everything looks good.
`));
}