From 8c34d810af95fae0ef846f54370a8c88bfab7123 Mon Sep 17 00:00:00 2001 From: "netop://ウィビ" Date: Sat, 11 Apr 2026 14:24:49 -0700 Subject: initial commit --- main.ts | 301 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 301 insertions(+) create mode 100644 main.ts (limited to 'main.ts') diff --git a/main.ts b/main.ts new file mode 100644 index 0000000..c3dbcc9 --- /dev/null +++ b/main.ts @@ -0,0 +1,301 @@ + + + +/*** IMPORT ------------------------------------------- ***/ + +import { + join, + green as shellGreen, + magenta as shellMagenta, + underline as shellUnderline +} from "dep/std.ts"; + +import { dedent } from "dep/x/dedent.ts"; + +/*** UTILITY ------------------------------------------ ***/ + +import { + environment, + errorMessage, + feedDirectory, + getVersion, + memoDirectory, + port, + remarkDirectory +} from "src/utility/constant.ts"; + +import createLayout from "src/helper/create-layout.ts"; +import getBinaryContents from "src/helper/get-binary-contents.ts"; +import getDirectoryContents from "src/helper/get-directory-contents.ts"; +import getDocuments from "src/helper/get-documents.ts"; +import getFileContents from "src/helper/get-file-contents.ts"; +import populateDocument from "src/helper/populate-document.ts"; +import populateRecents from "src/helper/populate-recents.ts"; + +/*** PROGRAM ------------------------------------------ ***/ + +const version = await getVersion(); + +const server = Deno.serve({ + handler: async(req) => { + const { origin, pathname } = new URL(req.url); + + if (pathname === "/2019-12-02-a-personal-api.txt") + return Response.redirect(origin + "/WM-042", 302); + + if (pathname === "/") { + const listings = await getDirectoryContents(memoDirectory); + + return new Response( + createLayout("memo", await populateDocument(listings[0]), populateRecents(listings, listings[0].filename)), { + headers: { + "content-type": "text/html; charset=utf-8" + } + } + ); + } + + if (pathname === "/remarks") { + const listings = await getDirectoryContents(remarkDirectory); + + return new Response( + createLayout("remark", await populateDocument(listings[0]), populateRecents(listings, listings[0].filename)), { + headers: { + "content-type": "text/html; charset=utf-8" + } + } + ); + } + + if (pathname === "/feed/atom") { + const filePath = join(feedDirectory, "index.xml"); + + return new Response( + await getFileContents(filePath), { + headers: { + "content-type": "application/atom+xml; charset=utf-8" + } + } + ); + } + + if (pathname === "/feed/json") { + const filePath = join(feedDirectory, "index.json"); + + return new Response( + await getFileContents(filePath), { + headers: { + "content-type": "application/feed+json; charset=utf-8" + } + } + ); + } + + if (pathname === "/feed/rss") { + const filePath = join(feedDirectory, "index.rss"); + + return new Response( + await getFileContents(filePath), { + headers: { + "content-type": "application/rss+xml; charset=utf-8" + } + } + ); + } + + if (pathname === "/type/400.woff2") { + const filePath = join("src", "asset", "type", "400.woff2"); + + return new Response( + await getBinaryContents(filePath), { + headers: { + "cache-control": "public, max-age=31536000, immutable", + "content-type": "font/woff2" + } + } + ); + } + + if (pathname === "/type/400i.woff2") { + const filePath = join("src", "asset", "type", "400i.woff2"); + + return new Response( + await getBinaryContents(filePath), { + headers: { + "cache-control": "public, max-age=31536000, immutable", + "content-type": "font/woff2" + } + } + ); + } + + if (pathname === "/type/600.woff2") { + const filePath = join("src", "asset", "type", "600.woff2"); + + return new Response( + await getBinaryContents(filePath), { + headers: { + "cache-control": "public, max-age=31536000, immutable", + "content-type": "font/woff2" + } + } + ); + } + + if (pathname === "/type/600i.woff2") { + const filePath = join("src", "asset", "type", "600i.woff2"); + + return new Response( + await getBinaryContents(filePath), { + headers: { + "cache-control": "public, max-age=31536000, immutable", + "content-type": "font/woff2" + } + } + ); + } + + if (/^\/(WM-\d*)$/.test(pathname)) { + const slug = pathname.slice(1) + ".txt"; + const posts = await getDocuments(memoDirectory); + + if (posts && posts.indexOf(slug) < 0) { + return new Response( + errorMessage, { + headers: { + "content-type": "text/plain; charset=utf-8" + } + } + ); + } + + const listings = await getDirectoryContents(memoDirectory); + + return new Response( + createLayout("memo", await populateDocument({ filename: slug }), populateRecents(listings, slug)), { + headers: { + "content-type": "text/html; charset=utf-8" + } + } + ); + } + + if (/^\/(WM-\d*).txt$/.test(pathname)) { + const slug = pathname.slice(1); + const posts = await getDocuments(memoDirectory); + + if (posts && posts.indexOf(slug) < 0) { + return new Response( + errorMessage, { + headers: { + "content-type": "text/plain; charset=utf-8" + } + } + ); + } + + const filePath = join(memoDirectory, slug); + + return new Response( + await getFileContents(filePath), { + headers: { + "content-type": "text/plain; charset=utf-8" + } + } + ); + } + + if (/^\/remarks\/(WR-\d*)$/.test(pathname)) { + const slug = pathname.split("/").pop() + ".txt"; + const posts = await getDocuments(remarkDirectory); + + if (posts && posts.indexOf(slug) < 0) { + return new Response( + errorMessage, { + headers: { + "content-type": "text/plain; charset=utf-8" + } + } + ); + } + + const listings = await getDirectoryContents(remarkDirectory); + + return new Response( + createLayout("remark", await populateDocument({ filename: slug }), populateRecents(listings, slug)), { + headers: { + "content-type": "text/html; charset=utf-8" + } + } + ); + } + + if (/^\/remarks\/(WR-\d*).txt$/.test(pathname)) { + const slug = String(pathname.split("/").pop()); + const documentArray = await getDocuments(remarkDirectory); + + if (documentArray && documentArray.indexOf(slug) < 0) { + return new Response( + errorMessage, { + headers: { + "content-type": "text/plain; charset=utf-8" + } + } + ); + } + + const filePath = join(remarkDirectory, slug); + + return new Response( + await getFileContents(filePath), { + headers: { + "content-type": "text/plain; charset=utf-8" + } + } + ); + } + + return new Response( + errorMessage, { + headers: { + "content-type": "text/plain; charset=utf-8" + } + } + ); /*** 404 by default ***/ + }, + hostname: "0.0.0.0", + onListen() { + console.log( + dedent`\n + ┌${repeatCharacter("─", 32)}┐ + │ ${fit("THE WEBB BLOG")} │ + │ ${fit(`→ ${environment}`)} │ + │ ${shellGreen(fit(version))} │ + └${repeatCharacter("─", 32)}┘ + LOCAL ${shellMagenta(`${shellUnderline(`${this.hostname}:${port}`)}`)} + \n` + ); + }, + port +}) as Deno.HttpServer; + +Deno.addSignalListener("SIGINT", gracefulShutdown); +Deno.addSignalListener("SIGTERM", gracefulShutdown); + +/*** HELPER ------------------------------------------- ***/ + +function fit(input: string) { + const remainingSpace = 30 - input.length; /*** 34 - 4 (border + one space each side) ***/ + return input + " ".repeat(remainingSpace); +} + +async function gracefulShutdown() { + await server.shutdown(); +} + +function repeatCharacter(input: string, repeatAmount: number): string { + if (!repeatAmount || repeatAmount <= 0) + return input; + + return input.repeat(repeatAmount); +} -- cgit v1.2.3