diff --git a/bun.lockb b/bun.lockb index 674491d..a9dfc97 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..86ef6ad --- /dev/null +++ b/index.ts @@ -0,0 +1,42 @@ +import SSSG from "sssg"; +import Variables from "sssg/src/plugins/variables"; +import Dev from "sssg/src/plugins/dev"; +import TSCompiler from "sssg/src/plugins/ts-compiler"; +import MarkdownMetadata from "sssg/src/plugins/markdown-metadata"; +import MarkdownCompiler from "sssg/src/plugins/markdown-compiler"; + +import * as path from "path"; +import * as fs from "fs"; + +const sssg = new SSSG({ + outputFolder: path.join(__dirname, "dist"), + inputFolder: path.join(__dirname, "website"), +}); + +await sssg.run({ + plugins: [ + new Variables(() => { + const variables: Record = { + __BLOG_POSTS__: JSON.stringify( + fs.readdirSync("./website/blogs").map((z) => z.replace(".md", "")) + ), + }; + + if (fs.existsSync("./website/templates")) { + for (const file of fs.readdirSync("./website/templates")) { + const id = file.toUpperCase().replace(".HTML", ""); + variables["__TEMPLATE_" + id + "__"] = fs + .readFileSync(path.join("./website/templates", file)) + .toString("utf8"); + } + } + return variables; + }), + new TSCompiler(), + new MarkdownMetadata(), + new MarkdownCompiler(), + new Dev(sssg), + ], +}); + +await sssg.build(); diff --git a/package.json b/package.json index 4d18e44..0df1d49 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "website2", - "module": "src/index.ts", + "module": "index.ts", "type": "module", "scripts": { - "prod": "bun src/index.ts --prod", - "dev": "bun src/index.ts --dev" + "prod": "bun index.ts --prod", + "dev": "bun index.ts --dev" }, "devDependencies": { "@types/bun": "latest" @@ -13,11 +13,6 @@ "typescript": "^5.0.0" }, "dependencies": { - "@types/mime-types": "^2.1.4", - "@types/p5": "^1.7.6", - "esbuild": "^0.23.0", - "marked": "^13.0.2", - "mime-types": "^2.1.35", - "preact": "^10.23.1" + "sssg": "git+https://git.sad.ovh/sophie/sssg#ef49a06be55dbb5277793d6cfcfa6736b7c1bc96" } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index 76899a1..0000000 --- a/src/index.ts +++ /dev/null @@ -1,111 +0,0 @@ -/* -⡿⣿⠿⢿⠿⣿⢿⡿⡿⡿⢿⠿⣿⠻⢟⡟⣋⣛⡻⡛⠋⠉⠀⠀⠀⠀⢈⡁⠉⢍⠛⡷⣀⠀⠀⠀⠀⠀⠀⠲⢂⠟⡁⢢⢛⡤⢁⣀⡠⣄ -⡳⡜⡺⢌⡳⢍⠎⡵⢣⢝⡩⢒⠡⠉⢈⣨⢗⡶⠛⠁⠀⠀⠀⠀⠉⢉⣲⣌⠑⢮⠑⠺⡅⠉⠁⠀⠒⠚⠷⣿⣌⡣⢜⠠⢎⠰⡉⠆⠱⠌ -⠱⠘⡑⠩⡉⢌⠲⡱⢩⣾⣫⣥⣶⣶⡿⣳⢏⣴⠎⠉⣹⢢⣀⣀⣶⡏⠀⠘⡷⣄⢳⡀⠘⢐⣶⣶⣶⣶⣦⠄⢾⡎⠢⡑⢨⢀⢠⡀⢎⠀ -⠣⡙⠬⠅⠁⠈⠁⠐⣿⣿⣿⣿⣿⣿⣿⣟⣾⣿⣀⣀⣈⣧⣿⣾⣿⣄⣀⡀⢽⣼⡄⢷⡤⣋⣿⣿⣿⣿⣿⣿⣮⣇⠀⠡⢃⡍⢢⣍⠳⣌ -⠂⡍⠂⠀⠀⠀⠀⠀⣹⣿⣿⣿⣿⣿⣿⣿⡟⠛⣿⣿⣏⣿⢻⡇⢀⣿⣿⣿⡿⣿⣿⡈⣷⡱⡞⣿⣿⣿⣿⣿⣿⣿⠀⠀⠢⠐⣃⢤⢫⡔ -⠐⠈⠁⠐⠒⠀⠁⠀⠘⣿⣿⣿⣿⣿⡿⣞⣿⡄⢿⣿⣿⡿⣼⣇⠀⣿⣿⣿⢧⣿⡿⣗⡸⢷⡍⢿⣿⣿⣿⣿⣿⡇⠒⠬⢓⡹⢰⢣⡓⢮ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⣿⣿⣿⣿⢿⣯⣿⣦⣙⣋⣵⣿⣿⣦⣌⣛⣽⣿⢯⣟⣧⡟⡼⣘⢧⣿⢻⣿⣿⠟⠐⡉⡒⠬⣁⠎⢦⠙⣃ -⢜⣩⢠⢠⠄⡄⢠⠄⢂⠄⡀⠙⣷⣿⡿⠿⠛⠋⠉⠉⠁⠀⠀⠀⠉⠈⠉⠉⠙⠛⠻⠾⣽⣷⡍⡖⣻⣿⡿⢣⢆⡣⢵⡉⢆⡥⣚⠦⣛⢤ -⢎⡔⣣⢎⡝⡸⢥⡺⢌⠴⡱⣬⠟⠁⢀⣠⠴⠶⠶⢛⠛⠋⠛⠛⠻⠶⢦⣄⠀⠀⠀⠀⠀⠈⠛⢧⡝⣿⠁⠜⠂⢧⠐⠈⠐⡄⠃⠘⠀⢂ -⢞⡼⡱⢞⡜⡳⢤⡙⣆⢦⣱⠏⠀⣰⣿⡃⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣻⣷⡀⠀⠀⠀⠀⠀⠈⢻⡅⡟⣈⠅⡆⢂⠈⡐⠀⠄⡀⠀⠀ -⠊⠼⠹⡄⡙⡜⢧⣽⢞⣮⡏⠀⢰⣿⣿⡿⢦⡌⣁⠒⠐⠂⠐⠀⠀⠐⢉⣩⣽⡇⠀⠀⠀⠀⠀⠀⠈⣷⣰⡌⠭⣰⢀⡱⠌⢢⠱⢠⠌⡘ -⡀⠤⠡⡼⢩⠛⠘⠜⡊⢹⡃⠀⠈⣿⣿⣿⣁⣎⣑⣪⣑⣣⣜⣰⢶⡾⡟⣤⣿⡿⠀⠀⠀⠀⠀⠀⠀⢸⣟⠾⡕⡁⣊⠱⢫⢄⠢⣅⢺⡰ -⠜⣰⢉⠲⣁⠚⡄⠈⡠⢐⡂⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⣿⡆⠙⢿⣧⢺⣥⠊⡑⠼⢲⠱ -⠑⡀⢎⡐⡡⢧⠙⣜⢣⢽⡇⠀⠀⠀⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⢀⡿⡏⠀⠀⠙⣷⡺⣝⢮⡳⢧⣋ -⠒⠀⠓⡀⠆⢜⠲⢨⡞⡞⣿⣷⣤⣀⠀⠀⢈⣻⣿⣿⣿⣿⣿⣿⡛⠉⠁⠀⠀⠀⠀⠀⠠⠔⠒⣲⡶⢻⡇⠀⠀⠀⠀⠘⢿⡜⢣⢌⡋⡝ -⣹⡖⢦⡴⢀⠞⣲⢏⡞⡡⢻⡀⠟⣫⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣦⣴⣦⣽⣷⣾⠟⠋⠁⣸⠀⠀⠀⠀⠹⡄⠘⢧⢡⡘⠲⣉ -⡣⣽⢲⡍⢯⡘⣷⢫⠔⠡⢻⡆⠀⠐⣿⣿⣽⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠋⠀⠀⢀⡇⠀⠀⠀⠀⠀⠠⣉⢚⣤⢂⠱⡶ -⣣⡙⢶⣘⣧⢼⡳⠃⡌⠐⣉⣇⠀⠀⠘⣿⣲⢻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠋⠀⠀⠀⡼⠀⠀⠀⠀⠀⠀⠀⢐⠎⣀⠉⠀⡈ -⢳⣏⢿⣹⣚⢧⡏⠡⢀⠃⢄⢻⡀⠀⠀⠘⢧⢋⢎⠻⡽⢿⢿⣿⣿⢿⡿⡟⢿⣹⡿⠁⠀⠀⠀⣸⠃⠀⠀⠀⠀⠀⠀⠀⠨⢆⡕⡘⠐⣃ -⣳⡾⣯⠷⠏⣿⠨⠁⠀⠈⢀⠊⢷⡀⠀⠀⠀⠁⠈⠁⠳⠌⠖⠌⠆⠃⠢⠽⠖⠉⠀⠀⠀⢀⣼⠃⢀⠀⠀⠀⠀⠀⠀⠀⠨⢇⠰⠉⠂⠀ -⣏⢷⡱⣎⢣⣏⠧⡀⠀⠀⠀⡜⢠⠿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⠟⠡⠈⠀⠀⠀⠀⠀⠀⠀⠀⢘⡆⠑⡂⠀⠀ -⡞⣦⢖⡫⣅⡾⢣⠅⡀⠀⡐⠤⢣⣻⢿⣿⣿⣶⣶⣤⣄⣀⣀⣀⣀⣀⣀⣠⣤⣶⡾⣟⡿⣥⢃⠂⠄⠀⠀⠀⠀⠀⠀⠀⡜⠤⢄⠀⠀⠀ -⣺⡅⢋⡑⣀⡿⣳⠌⡐⠀⠀⠀⠑⠸⢯⣿⣿⣿⢿⣿⢿⣿⢿⡿⣟⡿⣯⣟⣳⢧⣿⡿⣝⠢⣁⠂⠀⠀⠀⠀⠀⠀⠀⢀⠞⠀⠠⠔⠀⠂ -⡓⣆⢦⠳⡱⣹⢧⡷⣀⡀⠀⠀⠀⣀⠀⡀⣙⣿⣿⡿⣿⢾⣻⣽⣻⣽⣳⣯⣟⣿⣟⡳⠌⠂⠀⠀⠀⠀⠀⠀⠀⠀⠠⣜⠊⠤⠀⠀⠀⠀ -⣵⡼⣩⢮⣱⢯⣟⡷⣯⡽⣯⣻⡵⣮⣟⣽⣛⣿⣿⡿⣽⣯⣟⣾⣳⢯⣷⣻⣿⣿⣯⣷⡲⣄⡄⣠⣀⡀⣀⣀⡤⣔⠻⡄⢋⠜⠀⢠⡀⠀ -*/ -// Five at nit of fredyer -// Hor hor -export abstract class Plugin { - abstract name: string; - abstract rewriteTriggers: string[]; - renameTo?: string; - abstract longLasting: boolean; - - abstract rewriteFile( - file: string, - filePath: string - ): Promise; -} - -import * as fs from "fs"; -import * as path from "path"; - -if (!fs.existsSync("dist")) fs.mkdirSync("dist"); - -const plugins: Plugin[] = []; - -for await (const file of fs.readdirSync(path.join("src", "plugins"))) { - const clas = (await import(path.join(__dirname, "plugins", file))).default; - const plug = new clas(); - - plugins.push(plug); -} - -export async function build() { - try { - fs.rmdirSync("dist"); - } catch {} - - const sourceFiles = fs.readdirSync(path.join("website"), { - recursive: true, - withFileTypes: true, - }); - const globalPlugins = plugins.filter((z) => z.rewriteTriggers.includes("*")); - - for await (const file of sourceFiles) { - if (!file.isFile()) continue; - - const type = file.name.split(".").at(-1); - if (!type) continue; - - const shortname = file.name.slice(0, file.name.length - (type.length + 1)); - const availablePlugins = plugins.filter((z) => - z.rewriteTriggers.includes(type) - ); - - if (availablePlugins.length == 0) { - const oldPath = path.join(file.parentPath, file.name); - fs.cpSync(oldPath, oldPath.replace("website", "dist")); - } - - for await (const plugin of availablePlugins) { - const oldPath = path.join(file.parentPath, file.name); - const newPath = path - .join( - file.parentPath, - shortname + - "." + - (plugin.rewriteTriggers.includes("*") ? type : plugin.renameTo) - ) - .replace("website", "dist"); - let data = fs.readFileSync(oldPath).toString("utf8"); - - for await (const globalPlugin of globalPlugins) { - const rewritten = await globalPlugin.rewriteFile(data, oldPath); - if (!rewritten) continue; - data = rewritten; - } - - let rewrite = await plugin.rewriteFile(data, oldPath); - - if (!rewrite) continue; - - fs.mkdirSync(path.dirname(newPath), { recursive: true }); - fs.writeFileSync(newPath, rewrite); - } - } -} - -await build(); diff --git a/src/plugins/dev.ts b/src/plugins/dev.ts deleted file mode 100644 index 844e667..0000000 --- a/src/plugins/dev.ts +++ /dev/null @@ -1,96 +0,0 @@ -import type { Server, ServerWebSocket } from "bun"; -import { Plugin, build } from ".."; -import * as fs from "fs"; -import mime from "mime-types"; - -const script = `let reconnectTimeout;function connect(){console.log("[--dev] connecting to dev server");let ws=new WebSocket("ws://localhost:8080");ws.addEventListener("message",message=>{if(message.data=="refresh"){location.reload()}});ws.addEventListener("open",()=>{console.log("[--dev] connected")});ws.addEventListener("close",()=>{console.log("[--dev] socket closed, restarting in 1s");clearTimeout(reconnectTimeout);reconnectTimeout=setTimeout(()=>{connect()},1e3)})}window.addEventListener("load",()=>connect());`; - -export default class DevPlugin extends Plugin { - name = "dev"; - rewriteTriggers = []; - renameTo = undefined; - longLasting = true; - server!: Server; - allConnections: ServerWebSocket[] = []; - - constructor() { - super(); - if (!process.argv.includes("--dev")) return; - - fs.watch( - "./website", - { - recursive: true, - }, - async (e, f) => { - console.log("[dev] Noticed update in " + f + ", of type " + e + "."); - this.allConnections.forEach((z) => z.send("refresh")); - await build(); - } - ); - - this.server = Bun.serve({ - fetch(req, server) { - const success = server.upgrade(req); - if (success) { - return undefined; - } - - const url = new URL(req.url); - - let cleanedPath = url.pathname; - if (cleanedPath == "/") cleanedPath = "/index.html"; - if (cleanedPath.endsWith("/")) cleanedPath = cleanedPath.slice(0, -1); - - let fsPath = "./dist" + cleanedPath; - - if (fsPath.match(/\.\.\//g) !== null) { - return undefined; - } - let rawFile; - try { - rawFile = fs.readFileSync(fsPath); - } catch { - return new Response("404 Not Found", { - status: 404, - }); - } - const type = fsPath.split(".").at(-1); - if (!type) return; - if (type == "html") { - - rawFile = rawFile.toString().replace( - "", - `` - ); - } - return new Response(rawFile, { - headers: { - "Cache-Control": "no-cache, no-store, must-revalidate", - "Pragma": "no-cache", - "Expires": "0", - "Content-Type": (mime.lookup(type) || "application/octet-stream") + "; charset=utf-8", - }, - }); - }, - websocket: { - open: (ws) => { - ws.data = Math.random(); - - this.allConnections.push(ws); - }, - message(ws, message) {}, - close: (ws) => { - this.allConnections = this.allConnections.filter( - (z) => z.data != ws.data - ); - }, - }, - port: 8080, - }); - } - - async rewriteFile(file: string, filePath: string) { - return undefined; - } -} diff --git a/src/plugins/markdown-compiler.ts b/src/plugins/markdown-compiler.ts deleted file mode 100644 index f1a136b..0000000 --- a/src/plugins/markdown-compiler.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Plugin } from ".."; -import { marked } from "marked"; -import { parseMetadata } from "./markdown-metadata"; - -export default class MarkdownCompiler extends Plugin { - name = "markdown-compiler"; - rewriteTriggers = ["md"] - renameTo = "html" - longLasting = false; - - async rewriteFile(file: string, filePath: string) { - let text = file; - const metadata = parseMetadata(text); - if(metadata) { - let textSplit = text.split('\n'); - textSplit.splice(0, Object.keys(metadata).length); - textSplit.unshift(metadata.title) - text = textSplit.join("\n"); - } - return await marked.parse(text); - } -} \ No newline at end of file diff --git a/src/plugins/markdown-metadata.ts b/src/plugins/markdown-metadata.ts deleted file mode 100644 index 2b970e2..0000000 --- a/src/plugins/markdown-metadata.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Plugin } from ".."; - -export function parseMetadata(file: string) { - if (!/^=+$/gm.test(file)) return; - const splitfile = file.split("\n"); - let properties: Record | undefined; - for (let i = 0; i < splitfile.length; i++) { - if (!properties) properties = {}; - const line = splitfile[i]; - if (/^=+$/gm.test(line)) break; - const parts = line.split("="); - if (parts.length !== 2) break; - properties[parts[0].trim()] = parts[1].trim(); - } - return properties; -} - -export default class MarkdownMetadataGenerator extends Plugin { - name = "markdown-metadata"; - rewriteTriggers = ["md"]; - renameTo = "json"; - longLasting = false; - - async rewriteFile(file: string, filePath: string) { - const metadata = parseMetadata(file); - if (!metadata) return; - return JSON.stringify(metadata); - } -} diff --git a/src/plugins/ts-compiler.ts b/src/plugins/ts-compiler.ts deleted file mode 100644 index 5066e8a..0000000 --- a/src/plugins/ts-compiler.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Plugin } from ".."; -import * as fs from "fs"; -import * as esbuild from "esbuild"; - -export default class TSCompiler extends Plugin { - name = "ts-compiler"; - rewriteTriggers = ["ts", "tsx", "jsx"]; - renameTo = "js"; - longLasting = false; - - minify = false; - constructor() { - super(); - if (process.argv.includes("--prod")) { - this.minify = true; - } - } - async rewriteFile(file: string, filePath: string) { - let result; - try { - result = await esbuild.build({ - stdin: { - contents: file, - resolveDir: filePath.split("/")?.slice(0, -1).join("/"), - sourcefile: filePath.split("/").at(-1), - loader: filePath.split("/").at(-1)?.split(".").at(-1) as - | "ts" - | "tsx" - | "jsx", - }, - jsxFragment: "Fragment", - jsxFactory: "h", - jsxImportSource: "preact", - jsx: "transform", - write: false, - bundle: true, - outdir: "out", - minify: this.minify, - }); - } catch (e) { - console.error(e); - console.log("Errored!"); - return; - } - - if (result.errors.length != 0) { - console.log("TS compiler errored."); - result.errors.forEach((element) => { - console.error(element); - }); - } else { - const output = result.outputFiles[0].contents; - return new TextDecoder().decode(output); - } - } -} diff --git a/src/plugins/variables.ts b/src/plugins/variables.ts deleted file mode 100644 index a73abfe..0000000 --- a/src/plugins/variables.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Plugin } from ".."; -import * as fs from "fs"; -import * as path from "path"; - -export default class Variables extends Plugin { - name = "variables"; - rewriteTriggers = ["html", "*"]; - renameTo = undefined; - longLasting = false; - - variables: Record = {}; - - constructor() { - super(); - this.variables["__BLOG_POSTS__"] = JSON.stringify( - fs.readdirSync("./website/blogs").map((z) => z.replace(".md", "")) - ); - const templatePath = path.resolve(__dirname, "../../website/templates"); - if (fs.existsSync(templatePath)) { - for (const file of fs.readdirSync(templatePath)) { - const id = file.toUpperCase().replace(".HTML", ""); - this.variables["__TEMPLATE_" + id + "__"] = fs - .readFileSync(path.join(templatePath, file)) - .toString("utf8"); - } - } - } - - async rewriteFile(file: string, filePath: string): Promise { - let prevfile = file; - for (const a of Object.entries(this.variables)) { - prevfile = prevfile.replaceAll(a[0], a[1]); - } - return prevfile; - } -} diff --git a/src/readme.md b/src/readme.md deleted file mode 100644 index 4bf7df4..0000000 --- a/src/readme.md +++ /dev/null @@ -1,97 +0,0 @@ -# sad.ovh build system - -design goals: -1. rewrite and generate custom HTML/TS/JS/whatever.. -2. allow for variables and other important features in buildsystem->html -3. plugins, this ties together the top two -4. HMR and HTML/CSS reloading (in the Dev plugin) -5. Rewriteable file renaming -6. Every plugin runs on the same set of files, and can rename and reinject multiple times - -Psudeo-code build.ts - -```ts -class Plugin { - .. whatever's needed to support the plugin system .. -} - -if(.. not exist dist ..) - .. make dist .. -const plugins: Plugin[] = []; -.. dynamically load plugins into plugins .. - -const srcFiles: File[] = [] -.. get files into file .. - - -export function build () { - for(const file of srcFiles) { - const plugins = plugins.filter(z=>z.rewriteTriggers(file.type)); - if(plugins.length == 0) continue; - - for (const plugin of plugins) { - let filename = file.name + "." + file.type; - let newFilename = path.join("dist", file.name + "." + plugin.renameTo || file.type); - - fs.writeFileSync(newFilename, plugin.rewriteFile(fs.readFileSync(filename), filename)) - } - } -} - -build(); - -``` -Psudeo-code plugins -```ts -class DevPlugin extends Plugin { - rewriteTriggers: ["html"] - renameTo: undefined - longLasting: false; - .. websocket server .. - constructor(.. options from argv of the main executable..) { - .. ran on start of main index.ts executable .. - .. this would be long lasting, so leave if not using --dev .. - - .. use a method on the server that rebuilds if required .. - .. Would run a web server too .. - - } - - rewriteFile(file: string, filePath: string) { - return file.replace("", ``) - } -} -``` - -```ts -class TSCompiler extends Plugin { - rewriteTriggers: ["ts"] - renameTo: "js" - - rewriteFile(file: string, filePath: string) { - // use SWC or TS or esbuild, whatever - } -} -``` - -```ts -class MarkdownMetadataGenerator extends Plugin { - rewriteTriggers: ["md"] - renameTo: "json" - - rewriteFile(file: string, filePath: string) { - return marked.parse(file); - } -} -``` - -```ts -class MarkdownCompiler extends Plugin { - rewriteTriggers: ["md"] - renameTo: "html" - - rewriteFile(file: string, filePath: string) { - return marked.parse(file); - } -} -``` \ No newline at end of file diff --git a/website/scripts/blog_post.tsx b/website/scripts/blog_post.tsx index f304b46..cc70970 100644 --- a/website/scripts/blog_post.tsx +++ b/website/scripts/blog_post.tsx @@ -2,9 +2,8 @@ import { useEffect, useState } from "preact/hooks"; import type { Metadata } from "./blog"; import { Giscus } from "./giscus"; - export function BlogPost({ pageOpen }: { pageOpen: [Metadata | undefined, (z: Metadata | undefined) => void] }) { - if(!pageOpen[0]) return

How did you get to here..?

; + if (!pageOpen[0]) return

How did you get to here..?

; const blogPost = useState();