From 8c34d810af95fae0ef846f54370a8c88bfab7123 Mon Sep 17 00:00:00 2001 From: "netop://ウィビ" Date: Sat, 11 Apr 2026 14:24:49 -0700 Subject: initial commit --- src/helper/create-layout.ts | 276 +++++++++++++++++++++++++++++++++++ src/helper/get-binary-contents.ts | 13 ++ src/helper/get-directory-contents.ts | 34 +++++ src/helper/get-documents.ts | 35 +++++ src/helper/get-file-contents.ts | 14 ++ src/helper/parse-header.ts | 73 +++++++++ src/helper/populate-document.ts | 21 +++ src/helper/populate-recents.ts | 47 ++++++ 8 files changed, 513 insertions(+) create mode 100644 src/helper/create-layout.ts create mode 100644 src/helper/get-binary-contents.ts create mode 100644 src/helper/get-directory-contents.ts create mode 100644 src/helper/get-documents.ts create mode 100644 src/helper/get-file-contents.ts create mode 100644 src/helper/parse-header.ts create mode 100644 src/helper/populate-document.ts create mode 100644 src/helper/populate-recents.ts (limited to 'src/helper') diff --git a/src/helper/create-layout.ts b/src/helper/create-layout.ts new file mode 100644 index 0000000..6bd13cd --- /dev/null +++ b/src/helper/create-layout.ts @@ -0,0 +1,276 @@ + + + +/*** UTILITY ------------------------------------------ ***/ + +import { + author, + description, + title, + url +} from "src/utility/constant.ts"; + +import headerParser from "src/helper/parse-header.ts"; + +/*** EXPORT ------------------------------------------- ***/ + +export default (type: "memo" | "remark", memo: string, recents: string) => { + const { abstract, /*category,*/ document, title: documentTitle } = headerParser(memo); + + return ` + + + + + ${title} • ${String(documentTitle).toLowerCase()} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [homepage|forum|cv] + ${document} [text|html] + ${type === "memo" ? `[remarks]` : `[memos]`} +
+ +
+
+
+              ${memo}
+            
+
+ + +
+ + + + + `; +} diff --git a/src/helper/get-binary-contents.ts b/src/helper/get-binary-contents.ts new file mode 100644 index 0000000..df41228 --- /dev/null +++ b/src/helper/get-binary-contents.ts @@ -0,0 +1,13 @@ + + + +/*** EXPORT ------------------------------------------- ***/ + +export default async(filePath: string) => { + const fileExists = await Deno.readFile(filePath); + + if (!fileExists) + return ""; + + return fileExists; +} diff --git a/src/helper/get-directory-contents.ts b/src/helper/get-directory-contents.ts new file mode 100644 index 0000000..80fb20c --- /dev/null +++ b/src/helper/get-directory-contents.ts @@ -0,0 +1,34 @@ + + + +/*** EXPORT ------------------------------------------- ***/ + +export default async(directory: string): Promise<{ filename: string; }[]> => { + const documentArray: { filename: string; }[] = []; + + try { + const documents: Deno.DirEntry[] = []; + + for await (const dirEntry of Deno.readDir(directory)) { + if (dirEntry.isFile) + documents.push(dirEntry); + } + + documents.sort((a, b) => a.name.localeCompare(b.name)).reverse(); + + for (const document of documents) { + if (document.name.startsWith(".")) + return []; + + if (document.name.endsWith(".txt")) { + const data = { filename: document.name }; + documentArray.push(data); + } + } + } catch(error) { + console.error(`Error reading directory contents: ${String(error)}`); + } finally { + // deno-lint-ignore no-unsafe-finally + return documentArray; + } +} diff --git a/src/helper/get-documents.ts b/src/helper/get-documents.ts new file mode 100644 index 0000000..ca9ce93 --- /dev/null +++ b/src/helper/get-documents.ts @@ -0,0 +1,35 @@ + + + +/*** EXPORT ------------------------------------------- ***/ + +export default async(directory: string) => { + const posts: string[] = []; + + try { + const files: Deno.DirEntry[] = []; + + for await (const dirEntry of Deno.readDir(directory)) { + if (dirEntry.isFile) + files.push(dirEntry); + } + + /*** Deno is weird in that if you do NOT call `.reverse()` + it will NOT load everything in the directory…WTF?! ***/ + + files.sort((a, b) => a.name.localeCompare(b.name)).reverse(); + + for (const file of files) { + if (file.name.startsWith(".")) + return; + + if (file.name.endsWith(".txt")) + posts.push(file.name); + } + } catch(error) { + console.error(`Error reading directory for posts: ${String(error)}`); + } finally { + // deno-lint-ignore no-unsafe-finally + return posts; + } +} diff --git a/src/helper/get-file-contents.ts b/src/helper/get-file-contents.ts new file mode 100644 index 0000000..a159f95 --- /dev/null +++ b/src/helper/get-file-contents.ts @@ -0,0 +1,14 @@ + + + +/*** EXPORT ------------------------------------------- ***/ + +export default async(filePath: string) => { + const fileExists = await Deno.stat(filePath); + + if (!fileExists) + return ""; + + const content = await Deno.readTextFile(filePath); + return content; +} diff --git a/src/helper/parse-header.ts b/src/helper/parse-header.ts new file mode 100644 index 0000000..92e0e52 --- /dev/null +++ b/src/helper/parse-header.ts @@ -0,0 +1,73 @@ + + + +/*** EXPORT ------------------------------------------- ***/ + +export interface DocumentMeta { + abstract: string; + category: string; + date: string; + document: string; + title: string; +} + +export default (input: string): DocumentMeta => { + /*** NOTE + This is extremely fragile, the source document must be formatted + specifically. This is my blog so who cares? ***/ + + const lines = input.split("\n"); + + /*** extract document ID ***/ + const documentMatch = lines[1]?.match(/^Document:\s+(\S+)/); + const document = documentMatch?.[1] ?? ""; + + /*** extract category ***/ + const categoryMatch = lines[2]?.match(/^Category:\s+(\S+)/); + const category = categoryMatch?.[1] ?? ""; + + /*** extract date ***/ + const dateMatch = lines[2]?.match(/\d{4}.\d{2}.\d{2}/); + const date = dateMatch?.[0] ?? ""; + + /*** find title (first non-empty line after the header block) ***/ + let title = ""; + let titleIndex = -1; + + for (let i = 3; i < lines.length; i++) { + const trimmed = lines[i].trim(); + + if (trimmed && trimmed !== "Abstract") { + title = trimmed; + titleIndex = i; + break; + } + } + + /*** extract abstract (content between "Abstract" and "Body") ***/ + let abstract = ""; + let inAbstract = false; + + for (let i = titleIndex + 1; i < lines.length; i++) { + const trimmed = lines[i].trim(); + + if (trimmed === "Abstract") { + inAbstract = true; + continue; + } + + if (trimmed === "Body") + break; + + if (inAbstract && trimmed) + abstract += (abstract ? " " : "") + trimmed; + } + + return { + abstract, + category, + date, + document, + title + }; +} diff --git a/src/helper/populate-document.ts b/src/helper/populate-document.ts new file mode 100644 index 0000000..0c57707 --- /dev/null +++ b/src/helper/populate-document.ts @@ -0,0 +1,21 @@ + + + +/*** UTILITY ------------------------------------------ ***/ + +import { memoDirectory, remarkDirectory, remarkRegex } from "src/utility/constant.ts"; + +import getFileContents from "src/helper/get-file-contents.ts"; +import processMarkdown from "src/utility/markdown.ts"; + +/*** EXPORT ------------------------------------------- ***/ + +export default async(document: { filename: string; }): Promise => { + let isMemo = true; + + if (remarkRegex.test(document.filename)) + isMemo = false; + + const contents = await getFileContents(`${isMemo ? memoDirectory : remarkDirectory}/${document.filename}`); + return processMarkdown(contents); +} diff --git a/src/helper/populate-recents.ts b/src/helper/populate-recents.ts new file mode 100644 index 0000000..551434b --- /dev/null +++ b/src/helper/populate-recents.ts @@ -0,0 +1,47 @@ + + + +/*** UTILITY ------------------------------------------ ***/ + +import { remarkRegex } from "src/utility/constant.ts"; + +/*** EXPORT ------------------------------------------- ***/ + +export default (documentList: Array<{ filename: string; }>, currentDocument: string): string => { + const currentIndex = documentList.findIndex(item => item.filename === currentDocument); + let isMemo = true; + let maximumIndex = documentList.length; + let minimumIndex = 0; + + if (remarkRegex.test(currentDocument)) + isMemo = false; + + if (currentIndex < 7) + minimumIndex = 0; + else + minimumIndex = currentIndex - 7; + + if (currentIndex < (maximumIndex - 8)) + maximumIndex = currentIndex + 8; + + const documents = documentList.slice(minimumIndex, maximumIndex).map((arrayItem: { filename: string; }) => { + if (!arrayItem) + return ""; + + const { filename } = arrayItem; + + if (filename === currentDocument) { + if (isMemo) + return `${filename.replace(".txt", "")}`; + else + return `${filename.replace(".txt", "")}`; + } else { + if (isMemo) + return `${filename.replace(".txt", "")}`; + else + return `${filename.replace(".txt", "")}`; + } + }); + + return documents.join(""); +} -- cgit v1.2.3