From 187ecd905388d982b65f432eebb56c6bcd21bc98 Mon Sep 17 00:00:00 2001 From: ArmoryNode <22787155+ArmoryNode@users.noreply.github.com> Date: Sun, 26 Jan 2025 16:45:57 -0800 Subject: [PATCH] Cleaned up code, added documentation, converted CF function to typescript, and updated README --- README.md | 14 +++++++----- functions/{index.js => index.ts} | 23 +++++++++---------- scripts/build.ts | 26 ++++++++++++++------- scripts/clean.ts | 11 ++++++--- scripts/publish.ts | 39 +++++++++++++++++++------------- scripts/run.ts | 9 +++++--- src/assets/styles/main.scss | 3 +-- 7 files changed, 75 insertions(+), 50 deletions(-) rename functions/{index.js => index.ts} (77%) diff --git a/README.md b/README.md index 82bec43..65ab742 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ This repository contains the source code for my website. It's currently very min ## ๐Ÿ› ๏ธ Technology Used [![Elm](https://img.shields.io/badge/Elm-60B5CC?style=for-the-badge&logo=elm&logoColor=white)](https://elm-lang.org/) -[![Deno](https://img.shields.io/badge/Deno-000000?style=for-the-badge&logo=deno&logoColor=white)](https://deno.com/) [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white)](https://www.typescriptlang.org/) -[![Sass](https://img.shields.io/badge/Sass-CC6699?style=for-the-badge&logo=sass&logoColor=white)](https://sass-lang.com/) +[![Sass](https://img.shields.io/badge/Sass-CC6699?style=for-the-badge&logo=sass&logoColor=white)](https://sass-lang.com/)
+[![Deno](https://img.shields.io/badge/Deno-000000?style=for-the-badge&logo=deno&logoColor=white)](https://deno.com/) [![Cloudflare Pages](https://img.shields.io/badge/Cloudflare%20Pages-F38020?style=for-the-badge&logo=cloudflarepages&logoColor=white)](https://pages.cloudflare.com/) ## ๐Ÿ‘ทโ€โ™‚๏ธ Getting Started @@ -19,7 +19,7 @@ Since this is my personal website, I don't really expect anyone to want to run i - Elm (https://elm-lang.org/) - Deno (https://deno.com/) -- Wrangler (https://developers.cloudflare.com/workers/wrangler/install-and-update/) +- Node.js (https://nodejs.org/en) (This is only required until [this bug is fixed](https://github.com/denoland/deno/issues/26349)) ### Building 1. Clone the repository @@ -33,9 +33,11 @@ cd ArmoryNodeWebsite # Use this command to build and run the project deno task run -# Use this command if you only wish to generate the javascript and css -# (e.g. using your own web server) -deno task build +# On first run it will ask you to install wrangler (if you don't already have it). +# Just hit enter to continue, this will only need to be done once. +Need to install the following packages: +wrangler@x.x.x +Ok to proceed? (y) ``` The website should now be running at `http://localhost:8787` diff --git a/functions/index.js b/functions/index.ts similarity index 77% rename from functions/index.js rename to functions/index.ts index d86a090..004d479 100644 --- a/functions/index.js +++ b/functions/index.ts @@ -1,13 +1,11 @@ +import type { ExecutionContext } from "npm:@cloudflare/workers-types"; + /** * Injects `nonce` attribute into script and style tags to enable CSP. - * @param {any} context */ -export async function onRequest(context) { +export async function onRequest(context: ExecutionContext) { - /** - * @type {Response} - */ - const response = await context.next(); + const response: Response = await context.next(); const nonce = crypto.randomUUID(); // Remove the CSP header if the response is a 304 @@ -17,7 +15,7 @@ export async function onRequest(context) { return response; } - let html = await response.text(); + let html: string | null = await response.text(); if (html.trim() === '') { html = null; @@ -30,6 +28,10 @@ export async function onRequest(context) { const newResponse = new Response(html, response); const cspHeader = response.headers.get('Content-Security-Policy'); + + if (cspHeader === null) + return response; + const newCSPHeader = addNonceToCSPHeader(cspHeader, nonce); newResponse.headers.set('Content-Security-Policy', newCSPHeader); @@ -39,11 +41,8 @@ export async function onRequest(context) { /** * Adds a nonce to a CSP header - * @param {string} cspHeader - * @param {string} nonce - * @returns {string} */ -function addNonceToCSPHeader(cspHeader, nonce) { +function addNonceToCSPHeader(cspHeader: string, nonce: string) { const csp = cspHeader.split(';'); return csp.map((directive) => { if (directive.includes('script-src') || directive.includes('style-src')) { @@ -51,4 +50,4 @@ function addNonceToCSPHeader(cspHeader, nonce) { } return directive; }).join(';'); -} \ No newline at end of file +} diff --git a/scripts/build.ts b/scripts/build.ts index 39aeb98..7c3946e 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -2,19 +2,25 @@ import { compileToString as ElmCompile } from "https://deno.land/x/deno_elm_comp import { minify } from "npm:terser"; import * as sass from "npm:sass"; +/** + * Creates the directories for CSS and JS if they don't already exist. + */ async function createDirectories() { - await Deno.mkdir("./static/css", { recursive: true }).catch(error => { + await Deno.mkdir("./static/css").catch(error => { if (error instanceof Deno.errors.AlreadyExists) return; throw error; }); - await Deno.mkdir("./static/js", { recursive: true }).catch(error => { + await Deno.mkdir("./static/js").catch(error => { if (error instanceof Deno.errors.AlreadyExists) return; throw error; }); } +/** + * Compiles Elm code, minifies it, and writes it to the static/js directory. + */ async function compileAndMinifyElm() { try { const compiledJs = await ElmCompile("./src/Main.elm", { mode: "optimize" }); @@ -31,17 +37,21 @@ async function compileAndMinifyElm() { } } +/** + * Compiles SASS files and writes it to the static/css directory. + */ async function compileSass() { const compiledCss = sass.compile("./src/assets/styles/main.scss", { style: "compressed", sourceMap: false }); - await Deno.writeTextFile("./static/css/main.min.css", compiledCss.css, { - create: true - }); + await Deno.writeTextFile("./static/css/main.min.css", compiledCss.css); } -export async function compile() { +/** + * Compiles all assets. + */ +export async function compileAll() { await createDirectories(); console.log("๐ŸŽจ Compiling Sass..."); @@ -54,6 +64,6 @@ export async function compile() { // Only run if the script is run directly, not imported as a module if (import.meta.main) { - await compile(); + await compileAll(); console.log("โœ… Build complete!"); -} \ No newline at end of file +} diff --git a/scripts/clean.ts b/scripts/clean.ts index 8ba9b34..7e9f31b 100644 --- a/scripts/clean.ts +++ b/scripts/clean.ts @@ -1,5 +1,8 @@ import { removePublishDirectory } from "./publish.ts"; +/** + * Removes all files in the specified directories. + */ async function cleanDirectories(directories: string[]) { try { for (const dir of directories) { @@ -9,12 +12,14 @@ async function cleanDirectories(directories: string[]) { } } } catch (error) { - if (!(error instanceof Deno.errors.NotFound)) { + if (!(error instanceof Deno.errors.NotFound)) throw error; - } } } +/** + * Cleans all generated files and removes the publish (dist) directory. + */ export async function clean() { console.log("๐Ÿงน Cleaning generated files..."); @@ -26,4 +31,4 @@ export async function clean() { if (import.meta.main) { await clean(); console.log("โœ… Clean complete!"); -} \ No newline at end of file +} diff --git a/scripts/publish.ts b/scripts/publish.ts index 3314b96..c469b89 100644 --- a/scripts/publish.ts +++ b/scripts/publish.ts @@ -1,29 +1,36 @@ import * as fs from "jsr:@std/fs"; -import { compile } from "./build.ts"; +import { compileAll } from "./build.ts"; +/** + * Removes the publish directory (dist) if it exists. + * Silently fails if the directory doesn't exist. + */ export async function removePublishDirectory() { - try { - await Deno.remove("./dist", { recursive: true }); - } catch (error) { - if (!(error instanceof Deno.errors.NotFound)) - throw error; + try { + await Deno.remove("./dist", { recursive: true }); + } catch (error) { + if (!(error instanceof Deno.errors.NotFound)) { + throw error; } + } } -/// Builds and publishes necessary files to `dist/` for deployment. +/** + * Publishes the website files to the dist directory. + */ export async function publish() { - console.log("๐Ÿ—๏ธ Running build step..."); - await compile(); + console.log("๐Ÿ—๏ธ Running build step..."); + await compileAll(); - console.log("๐Ÿš€ Publishing files to `dist/`..."); + console.log("๐Ÿš€ Publishing files to `dist/`..."); - await removePublishDirectory(); - await fs.copy("./static", "./dist/"); - await fs.copy("./wrangler.toml", "./dist/wrangler.toml"); + await removePublishDirectory(); + await fs.copy("./static", "./dist"); // Copy static files to dist + await fs.copy("./wrangler.toml", "./dist/wrangler.toml"); } // Only run if the script is run directly, not imported as a module if (import.meta.main) { - await publish(); - console.log("โœ… Publish complete!"); -} \ No newline at end of file + await publish(); + console.log("โœ… Publish complete!"); +} diff --git a/scripts/run.ts b/scripts/run.ts index 72bd6ef..4533061 100644 --- a/scripts/run.ts +++ b/scripts/run.ts @@ -1,9 +1,12 @@ -import { compile } from "./build.ts"; +import { compileAll } from "./build.ts"; +/** + * Compiles all assets and starts the wrangler dev server. + */ async function runTasks() { try { // Compile SASS and Elm files - await compile(); + await compileAll(); // Run wrangler console.log("๐Ÿค  Running Wrangler..."); @@ -25,4 +28,4 @@ async function runTasks() { } // This one should be run directly -await runTasks(); \ No newline at end of file +await runTasks(); diff --git a/src/assets/styles/main.scss b/src/assets/styles/main.scss index 255f11b..ee21d25 100644 --- a/src/assets/styles/main.scss +++ b/src/assets/styles/main.scss @@ -215,7 +215,6 @@ body { top: 0; width: 100%; height: 100%; - // box-shadow: rgba(0, 0, 0, 0.25) 0px 14px 28px, rgba(0, 0, 0, 0.22) 0px 10px 10px; opacity: 0; @include transition-for(opacity); } @@ -256,4 +255,4 @@ body { transform: translateY(0); opacity: 1; } -} \ No newline at end of file +}