From ba285543c2c583e3f59f1c7956c8c31c82896f70 Mon Sep 17 00:00:00 2001
From: Ethan Davidson <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Thu, 22 Feb 2024 23:36:57 -0800
Subject: [PATCH] replace `workshops.yaml` with `spring2024.yaml`
---
deno.jsonc | 2 +-
deno.lock | 1 -
deps.ts | 1 +
lib/workshops/mod.ts | 1 +
lib/workshops/ssr.tsx | 38 ++++++---------
lib/workshops/walk.ts | 17 +++++++
lib/workshops/workshops.ts | 51 +++++--------------
main.tsx | 54 ++++++++++++---------
workshops.yaml => workshops/spring2024.yaml | 3 --
9 files changed, 77 insertions(+), 91 deletions(-)
create mode 100644 lib/workshops/walk.ts
rename workshops.yaml => workshops/spring2024.yaml (89%)
diff --git a/deno.jsonc b/deno.jsonc
index 5902f6d..99231a4 100644
--- a/deno.jsonc
+++ b/deno.jsonc
@@ -1,7 +1,7 @@
{
"tasks": {
"lock": "deno cache --lock=deno.lock --lock-write deps.ts",
- "udd": "deno run -Ar https://deno.land/x/udd/main.tsx deps.ts && deno task lock",
+ "udd": "deno run -Ar https://deno.land/x/udd/main.ts deps.ts && deno task lock",
"build": "deno run -A main.tsx",
"dev": "deno run -A --watch main.tsx",
"serve": "deno run -A https://deno.land/std/http/file_server.ts build"
diff --git a/deno.lock b/deno.lock
index 6f05ad9..26fa1cd 100644
--- a/deno.lock
+++ b/deno.lock
@@ -143,7 +143,6 @@
"https://deno.land/x/nano_jsx@v0.1.0/htm/constants.ts": "3f296f87f03bd0ba8d7673884a1f6c4c927a2774648eaa4fd3ca9e3c46c3f7b8",
"https://deno.land/x/nano_jsx@v0.1.0/htm/index.ts": "29912b9f7a760884fce79caca82649b9772cfa3c3272e0426a4ce377b67d70d5",
"https://deno.land/x/nano_jsx@v0.1.0/index.ts": "0f39c911a39c61cb39f9bd8a2481500126dcb1b2a826d5b4523dd47a08b6938d",
- "https://deno.land/x/nano_jsx@v0.1.0/jsx-runtime/index.ts": "eb3d0884774eb3bf360d731bd7787aef2701f1be7e91aff8f88da59153d6aaa5",
"https://deno.land/x/nano_jsx@v0.1.0/jsx.ts": "7d5b4d4a249fba1a42f2016f54f71ca049d96ff490e098db4a19b2a9b197b952",
"https://deno.land/x/nano_jsx@v0.1.0/lazy.ts": "f8b8a2b915daff1fb70704ffad5171c805f1e28778b5cd0f8c827780762776c4",
"https://deno.land/x/nano_jsx@v0.1.0/mod.ts": "3dda2bc0dbee9abd01c03acf43ab55a7854952afe0450245fc2ad12eb9bd9598",
diff --git a/deps.ts b/deps.ts
index 430284b..79b1441 100644
--- a/deps.ts
+++ b/deps.ts
@@ -1,5 +1,6 @@
export { test } from "https://deno.land/std@0.217.0/front_matter/mod.ts";
export { copy, expandGlob } from "https://deno.land/std@0.217.0/fs/mod.ts";
+export { join } from "https://deno.land/std@0.217.0/path/join.ts";
export { parseArgs } from "https://deno.land/std@0.217.0/cli/parse_args.ts";
export { extract } from "https://deno.land/std@0.217.0/front_matter/any.ts";
export { parse as parseYAML } from "https://deno.land/std@0.217.0/yaml/mod.ts";
diff --git a/lib/workshops/mod.ts b/lib/workshops/mod.ts
index 66e07b6..c96f635 100644
--- a/lib/workshops/mod.ts
+++ b/lib/workshops/mod.ts
@@ -1,2 +1,3 @@
export * from "./workshops.ts";
export * from "./ssr.tsx";
+export * from "./walk.ts";
diff --git a/lib/workshops/ssr.tsx b/lib/workshops/ssr.tsx
index d80eef7..26c8266 100644
--- a/lib/workshops/ssr.tsx
+++ b/lib/workshops/ssr.tsx
@@ -1,11 +1,7 @@
import { Helmet } from "#/deps.ts";
import { withLayout } from "#/lib/shared/layout/mod.ts";
import { PageHeading } from "#/lib/shared/page_heading/mod.ts";
-import {
- DEFAULT_GROUP_ID,
- type Workshop,
- type WorkshopGroups,
-} from "./workshops.ts";
+import type { Workshop, WorkshopGroup } from "./workshops.ts";
function WorkshopPreviewComponent(props: { workshop: Workshop }) {
if (!props.workshop.url) {
@@ -16,7 +12,7 @@ function WorkshopPreviewComponent(props: { workshop: Workshop }) {
}
function WorkshopGroupsTableComponent(
- props: { workshopGroups: WorkshopGroups },
+ props: { workshopGroups: WorkshopGroup[] },
) {
return (
@@ -24,16 +20,13 @@ function WorkshopGroupsTableComponent(
Series |
Workshops |
- {Object.keys(props.workshopGroups)
- .filter((groupID) => groupID !== DEFAULT_GROUP_ID)
- .map((groupID) => (
+ {props.workshopGroups
+ .map((group) => (
- {groupID}
- |
-
- {props.workshopGroups[groupID].length}
+ {group.groupID}
|
+ {group.workshops.length} |
))}
@@ -41,7 +34,7 @@ function WorkshopGroupsTableComponent(
}
function WorkshopGroupsPageComponent(
- props: { workshopGroups: WorkshopGroups },
+ props: { workshopGroups: WorkshopGroup[] },
) {
return (
@@ -63,7 +56,7 @@ function WorkshopGroupsPageComponent(
}
export function renderWorkshopGroupsPageHTML(
- workshopGroups: WorkshopGroups,
+ workshopGroups: WorkshopGroup[],
) {
return withLayout(
,
@@ -98,32 +91,31 @@ function WorkshopGroupTableComponent(
}
function WorkshopGroupPageComponent(
- props: { groupID: string; workshops: Workshop[] },
+ props: { group: WorkshopGroup },
) {
return (
- {props.groupID} - Open Source Software workshops
+ {props.group.groupID} - Open Source Software workshops
- {props.groupID}
-
+ {props.group.groupID}
+
);
}
export function renderWorkshopGroupPageHTML(
- groupID: string,
- workshops: Workshop[],
+ group: WorkshopGroup,
) {
return withLayout(
- ,
+ ,
);
}
diff --git a/lib/workshops/walk.ts b/lib/workshops/walk.ts
new file mode 100644
index 0000000..f6e5f90
--- /dev/null
+++ b/lib/workshops/walk.ts
@@ -0,0 +1,17 @@
+import { expandGlob } from "#/deps.ts";
+import type { WorkshopGroup } from "./workshops.ts";
+import { parseWorkshopsYAML } from "./workshops.ts";
+
+function trimExtension(path: string): string {
+ return path.replace(/\.[^.]*$/, "");
+}
+
+export async function* walkWorkshopsYAML(glob: string | URL) {
+ for await (const stat of expandGlob(glob)) {
+ const content = await Deno.readTextFile(stat.path);
+ const groupID = trimExtension(stat.name);
+ const workshops = parseWorkshopsYAML(content);
+ const group: WorkshopGroup = { groupID, workshops };
+ yield group;
+ }
+}
diff --git a/lib/workshops/workshops.ts b/lib/workshops/workshops.ts
index 28e7864..ed47024 100644
--- a/lib/workshops/workshops.ts
+++ b/lib/workshops/workshops.ts
@@ -1,10 +1,14 @@
import { parseYAML } from "#/deps.ts";
+export interface WorkshopGroup {
+ groupID: string;
+ workshops: Workshop[];
+}
+
export interface Workshop {
title: string;
description?: string;
timestamp: string;
- group_id?: string;
url?: string;
}
@@ -13,28 +17,21 @@ export function isWorkshop(obj: unknown): obj is Workshop {
typeof obj === "object" &&
obj !== null &&
typeof (obj as Workshop).title === "string" &&
+ (obj as Workshop).description === undefined ||
+ typeof (obj as Workshop).description === "string" &&
typeof (obj as Workshop).timestamp === "string" &&
- (obj as Workshop).group_id === undefined ||
- typeof (obj as Workshop).group_id === "string" &&
(obj as Workshop).url === undefined ||
typeof (obj as Workshop).url === "string"
);
}
export function isWorkshops(obj: unknown): obj is Workshop[] {
- return Array.isArray(obj) && obj.every(isWorkshop);
-}
-
-export function parseWorkshops(content: string): Workshop[] {
- const workshops = JSON.parse(content);
- if (!isWorkshops(workshops)) {
- throw new Error("Invalid workshops");
- }
-
- return workshops;
+ return Array.isArray(obj) && obj.every((workshop) => isWorkshop(workshop));
}
-export function parseWorkshopsYAML(content: string): Workshop[] {
+export function parseWorkshopsYAML(
+ content: string,
+): Workshop[] {
const workshops = parseYAML(content);
if (!isWorkshops(workshops)) {
throw new Error("Invalid workshops");
@@ -42,29 +39,3 @@ export function parseWorkshopsYAML(content: string): Workshop[] {
return workshops;
}
-
-export const DEFAULT_GROUP_ID = "-";
-
-export function groupWorkshops(
- workshops: Workshop[],
- defaultGroupID = DEFAULT_GROUP_ID,
-) {
- const groups: Record = {};
- for (const workshop of workshops) {
- const groupID = workshop.group_id ?? defaultGroupID;
- if (!(groupID in groups)) {
- groups[groupID] = [];
- }
-
- groups[groupID].push(workshop);
- }
-
- // Sort the workshops by timestamp.
- for (const groupID in groups) {
- groups[groupID].sort((a, b) => a.timestamp.localeCompare(b.timestamp));
- }
-
- return groups;
-}
-
-export type WorkshopGroups = ReturnType;
diff --git a/main.tsx b/main.tsx
index 2f192b4..660fa5b 100644
--- a/main.tsx
+++ b/main.tsx
@@ -6,13 +6,14 @@ import {
walkProjects,
} from "#/lib/projects/mod.ts";
import {
- groupWorkshops,
- parseWorkshopsYAML,
renderWorkshopGroupPageHTML,
renderWorkshopGroupsPageHTML,
+ walkWorkshopsYAML,
+ type WorkshopGroup,
} from "#/lib/workshops/mod.ts";
-import { withLayout } from "./lib/shared/layout/mod.ts";
+import { withLayout } from "#/lib/shared/layout/mod.ts";
import { PageHeading } from "#/lib/shared/page_heading/mod.ts";
+import { join } from "#/deps.ts";
// Build script for generating static site from markdown files
// in the projects directory.
@@ -25,50 +26,57 @@ async function main(args: string[]) {
staticdir: ["s"],
},
default: {
- indir: "projects",
+ indir: "./",
outdir: "build",
staticdir: "static",
},
});
- // Create outdir if it does not exist.
- await Deno.mkdir(flags.outdir, { recursive: true });
+ // Create projects directory if it does not exist.
+ await Deno.mkdir(join(flags.outdir, "projects"), { recursive: true });
// Render projects assets.
const projects: Project[] = [];
- for await (const project of walkProjects(`${flags.indir}/*.md`)) {
+ for await (
+ const project of walkProjects(join(flags.indir, "projects", "*.md"))
+ ) {
projects.push(project);
const html = renderProjectPageHTML(project, flags["base-url"]);
- await Deno.writeTextFile(`${flags.outdir}/${project.id}.html`, html);
+ await Deno.writeTextFile(
+ join(flags.outdir, "projects", `${project.id}.html`),
+ html,
+ );
const json = JSON.stringify(project, null, 2);
- await Deno.writeTextFile(`${flags.outdir}/${project.id}.json`, json);
+ await Deno.writeTextFile(
+ join(flags.outdir, "projects", `${project.id}.json`),
+ json,
+ );
}
const projectsIndexHTML = await renderProjectsPageHTML(projects);
await Deno.writeTextFile(
- `${flags.outdir}/projects.html`,
+ join(flags.outdir, "projects.html"),
projectsIndexHTML,
);
// Create workshops directory if it does not exist.
- await Deno.mkdir(`${flags.outdir}/workshops`, { recursive: true });
+ await Deno.mkdir(join(flags.outdir, "series"), { recursive: true });
// Render workshops assets.
- const workshopsYAML = await Deno.readTextFile("workshops.yaml");
- const workshopGroups = groupWorkshops(parseWorkshopsYAML(workshopsYAML));
- for (const groupID in workshopGroups) {
- const workshopIndexHTML = renderWorkshopGroupPageHTML(
- groupID,
- workshopGroups[groupID],
- );
-
+ const workshopGroups: WorkshopGroup[] = [];
+ for await (
+ const group of walkWorkshopsYAML(join(flags.indir, "workshops", "*.yaml"))
+ ) {
+ workshopGroups.push(group);
+ const html = renderWorkshopGroupPageHTML(group);
await Deno.writeTextFile(
- `${flags.outdir}/workshops/${groupID}.html`,
- workshopIndexHTML,
+ join(flags.outdir, "series", `${group.groupID}.html`),
+ html,
);
+ const json = JSON.stringify(group, null, 2);
await Deno.writeTextFile(
- `${flags.outdir}/workshops/${groupID}.json`,
- JSON.stringify(workshopGroups[groupID], null, 2),
+ join(flags.outdir, "series", `${group.groupID}.json`),
+ json,
);
}
diff --git a/workshops.yaml b/workshops/spring2024.yaml
similarity index 89%
rename from workshops.yaml
rename to workshops/spring2024.yaml
index 387f65a..a05a46b 100644
--- a/workshops.yaml
+++ b/workshops/spring2024.yaml
@@ -1,17 +1,14 @@
- title: "Spring 2024 Open Source Software Kickoff"
description: "Launch into the vast expanse of collaborative development, exploring new frontiers and innovating together!"
timestamp: "2024-02-08"
- group_id: "spring2024"
url: "https://acmcsuf.com/spring24-oss-kickoff"
- title: "Making First Contributions"
description: "Make your first open source contribution and learn the basics of Git and GitHub."
timestamp: "2024-02-15"
- group_id: "spring2024"
url: "https://acmcsuf.com/1st-slides"
- title: "How to win FullyHacks"
description: "How to win a hackathon, and how to win FullyHacks in particular."
timestamp: "2024-02-22"
- group_id: "spring2024"
url: "https://acmcsuf.com/winning-fh"