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( - {Object.keys(props.workshopGroups) - .filter((groupID) => groupID !== DEFAULT_GROUP_ID) - .map((groupID) => ( + {props.workshopGroups + .map((group) => ( - + ))}
Series Workshops
- {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"