Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/)<br>
[![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
Expand All @@ -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
Expand All @@ -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`
Expand Down
23 changes: 11 additions & 12 deletions functions/index.js → functions/index.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -39,16 +41,13 @@ 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')) {
return `${directive} 'nonce-${nonce}'`;
}
return directive;
}).join(';');
}
}
26 changes: 18 additions & 8 deletions scripts/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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" });
Expand All @@ -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...");
Expand All @@ -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!");
}
}
11 changes: 8 additions & 3 deletions scripts/clean.ts
Original file line number Diff line number Diff line change
@@ -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) {
Expand All @@ -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...");

Expand All @@ -26,4 +31,4 @@ export async function clean() {
if (import.meta.main) {
await clean();
console.log("✅ Clean complete!");
}
}
39 changes: 23 additions & 16 deletions scripts/publish.ts
Original file line number Diff line number Diff line change
@@ -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!");
}
await publish();
console.log("✅ Publish complete!");
}
9 changes: 6 additions & 3 deletions scripts/run.ts
Original file line number Diff line number Diff line change
@@ -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...");
Expand All @@ -25,4 +28,4 @@ async function runTasks() {
}

// This one should be run directly
await runTasks();
await runTasks();
3 changes: 1 addition & 2 deletions src/assets/styles/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -256,4 +255,4 @@ body {
transform: translateY(0);
opacity: 1;
}
}
}
Loading