reformat + add testing utils, test dev plugin fully
This commit is contained in:
parent
0259a96937
commit
4d8a9dff8e
15 changed files with 242 additions and 158 deletions
|
|
@ -2,8 +2,8 @@ import { expect, test, beforeAll, afterAll } from "bun:test";
|
||||||
import SSSG, { Plugin } from "../index";
|
import SSSG, { Plugin } from "../index";
|
||||||
import { mkdirSync, existsSync, rmSync } from "fs";
|
import { mkdirSync, existsSync, rmSync } from "fs";
|
||||||
import { before } from "node:test";
|
import { before } from "node:test";
|
||||||
|
import { INPUT_FOLDER, nuke, OUTPUT_FOLDER } from "./util";
|
||||||
|
|
||||||
// Dummy plugin for basic testing
|
|
||||||
class DummyPlugin extends Plugin {
|
class DummyPlugin extends Plugin {
|
||||||
name = "dummy";
|
name = "dummy";
|
||||||
rewriteTriggers = ["txt"];
|
rewriteTriggers = ["txt"];
|
||||||
|
|
@ -17,27 +17,8 @@ class DummyPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure "input" folder exists before tests, and clean up after
|
|
||||||
const INPUT_FOLDER = "input";
|
|
||||||
const OUTPUT_FOLDER = "output";
|
|
||||||
|
|
||||||
beforeAll(() => {
|
nuke();
|
||||||
if (!existsSync(INPUT_FOLDER)) {
|
|
||||||
mkdirSync(INPUT_FOLDER);
|
|
||||||
}
|
|
||||||
if (!existsSync(OUTPUT_FOLDER)) {
|
|
||||||
mkdirSync(OUTPUT_FOLDER);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(() => {
|
|
||||||
if (existsSync(INPUT_FOLDER)) {
|
|
||||||
rmSync(INPUT_FOLDER, { recursive: true, force: true });
|
|
||||||
}
|
|
||||||
if (existsSync(OUTPUT_FOLDER)) {
|
|
||||||
rmSync(OUTPUT_FOLDER, { recursive: true, force: true });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test("SSSG initializes with input/output folders", () => {
|
test("SSSG initializes with input/output folders", () => {
|
||||||
const sssg = new SSSG({ inputFolder: INPUT_FOLDER, outputFolder: OUTPUT_FOLDER });
|
const sssg = new SSSG({ inputFolder: INPUT_FOLDER, outputFolder: OUTPUT_FOLDER });
|
||||||
|
|
@ -52,8 +33,6 @@ test("SSSG run sets plugins", async () => {
|
||||||
expect(sssg.plugins[0].name).toBe("dummy");
|
expect(sssg.plugins[0].name).toBe("dummy");
|
||||||
});
|
});
|
||||||
|
|
||||||
// More advanced build tests would require mocking fs and path, which Bun supports via bun:mock or manual stubbing.
|
|
||||||
// For now, we check plugin build invocation.
|
|
||||||
test("Plugin build is called", async () => {
|
test("Plugin build is called", async () => {
|
||||||
let called = false;
|
let called = false;
|
||||||
class BuildPlugin extends DummyPlugin {
|
class BuildPlugin extends DummyPlugin {
|
||||||
|
|
|
||||||
25
src/__tests__/util.ts
Normal file
25
src/__tests__/util.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
import {existsSync, mkdirSync, rmSync} from "fs"
|
||||||
|
import {beforeAll, afterAll} from "bun:test"
|
||||||
|
|
||||||
|
export const INPUT_FOLDER = "input";
|
||||||
|
export const OUTPUT_FOLDER = "output";
|
||||||
|
|
||||||
|
export function nuke() {
|
||||||
|
beforeAll(() => {
|
||||||
|
if (!existsSync(INPUT_FOLDER)) {
|
||||||
|
mkdirSync(INPUT_FOLDER);
|
||||||
|
}
|
||||||
|
if (!existsSync(OUTPUT_FOLDER)) {
|
||||||
|
mkdirSync(OUTPUT_FOLDER);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
if (existsSync(INPUT_FOLDER)) {
|
||||||
|
rmSync(INPUT_FOLDER, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
if (existsSync(OUTPUT_FOLDER)) {
|
||||||
|
rmSync(OUTPUT_FOLDER, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,97 @@
|
||||||
import { expect, test } from "bun:test";
|
import { expect, test, describe } from "bun:test";
|
||||||
import DevPlugin from "../dev";
|
import DevPlugin from "../dev";
|
||||||
import SSSG from "../../index";
|
import SSSG from "../../index";
|
||||||
|
import { INPUT_FOLDER, OUTPUT_FOLDER, nuke } from "../../__tests__/util";
|
||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
nuke();
|
||||||
|
|
||||||
// DevPlugin is too hard to test yet, this will take some time to finish.
|
describe("DevPlugin", () => {
|
||||||
//
|
test("starts server and serves injected HTML", async () => {
|
||||||
|
const sssg = new SSSG({ inputFolder: INPUT_FOLDER, outputFolder: OUTPUT_FOLDER });
|
||||||
|
fs.writeFileSync(path.join(OUTPUT_FOLDER, "index.html"), "<html><head></head><body>ok</body></html>");
|
||||||
|
|
||||||
|
const dev = new DevPlugin(sssg, {}, 8123);
|
||||||
|
const res = await fetch("http://localhost:8123/");
|
||||||
|
const body = await res.text();
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(body).toContain("<script>");
|
||||||
|
expect(body).toContain("ws://localhost:8080");
|
||||||
|
expect(res.headers.get("content-type")).toContain("text/html");
|
||||||
|
|
||||||
|
dev.server.stop(true);
|
||||||
|
dev.watcher.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("serves static files correctly", async () => {
|
||||||
|
fs.writeFileSync(path.join(OUTPUT_FOLDER, "style.css"), "body{}");
|
||||||
|
const sssg = new SSSG({ inputFolder: INPUT_FOLDER, outputFolder: OUTPUT_FOLDER });
|
||||||
|
const dev = new DevPlugin(sssg, {}, 8124);
|
||||||
|
|
||||||
|
const res = await fetch("http://localhost:8124/style.css");
|
||||||
|
const text = await res.text();
|
||||||
|
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
expect(res.headers.get("content-type")).toContain("text/css");
|
||||||
|
expect(text).toBe("body{}");
|
||||||
|
|
||||||
|
dev.server.stop(true);
|
||||||
|
dev.watcher.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("returns 404 on missing file", async () => {
|
||||||
|
const sssg = new SSSG({ inputFolder: INPUT_FOLDER, outputFolder: OUTPUT_FOLDER });
|
||||||
|
const dev = new DevPlugin(sssg, {}, 8125);
|
||||||
|
|
||||||
|
const res = await fetch("http://localhost:8125/nope.txt");
|
||||||
|
expect(res.status).toBe(404);
|
||||||
|
|
||||||
|
dev.server.stop(true);
|
||||||
|
dev.watcher.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("handles websocket connections and disconnects", async () => {
|
||||||
|
const sssg = new SSSG({ inputFolder: INPUT_FOLDER, outputFolder: OUTPUT_FOLDER });
|
||||||
|
const dev = new DevPlugin(sssg, {}, 8126);
|
||||||
|
|
||||||
|
const ws = new WebSocket("ws://localhost:8126");
|
||||||
|
await new Promise<void>(resolve => ws.addEventListener("open", () => resolve()));
|
||||||
|
expect(dev.allConnections.length).toBe(1);
|
||||||
|
|
||||||
|
ws.close();
|
||||||
|
await new Promise(r => setTimeout(r, 50));
|
||||||
|
expect(dev.allConnections.length).toBe(0);
|
||||||
|
|
||||||
|
dev.server.stop(true);
|
||||||
|
dev.watcher.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("detects file changes, triggers build, and refreshes", async () => {
|
||||||
|
const sssg = new SSSG({ inputFolder: INPUT_FOLDER, outputFolder: OUTPUT_FOLDER });
|
||||||
|
let buildCalled = false;
|
||||||
|
sssg.build = async () => { buildCalled = true; };
|
||||||
|
|
||||||
|
const dev = new DevPlugin(sssg, {}, 8127);
|
||||||
|
|
||||||
|
const ws = new WebSocket("ws://localhost:8127");
|
||||||
|
await new Promise<void>(resolve => ws.addEventListener("open", () => resolve()));
|
||||||
|
|
||||||
|
let gotRefresh = false;
|
||||||
|
ws.addEventListener("message", msg => {
|
||||||
|
if (msg.data === "refresh") gotRefresh = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.writeFileSync(path.join(INPUT_FOLDER, "test.txt"), "changed");
|
||||||
|
|
||||||
|
await new Promise(r => setTimeout(r, 300));
|
||||||
|
|
||||||
|
expect(buildCalled).toBeTrue();
|
||||||
|
expect(gotRefresh).toBeTrue();
|
||||||
|
|
||||||
|
ws.close();
|
||||||
|
dev.server.stop(true);
|
||||||
|
dev.watcher.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
import { expect, test } from "bun:test";
|
import { expect, test } from "bun:test";
|
||||||
import ImageOptimization from "../image-optimization";
|
import ImageOptimization from "../image-optimization";
|
||||||
|
|
||||||
// Minimal valid image buffers for each format
|
|
||||||
function loadSampleImage(ext: string): Buffer {
|
function loadSampleImage(ext: string): Buffer {
|
||||||
switch (ext) {
|
switch (ext) {
|
||||||
case "png":
|
case "png":
|
||||||
// 1x1 transparent PNG
|
|
||||||
return Buffer.from([
|
return Buffer.from([
|
||||||
0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,
|
0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,
|
||||||
0x00,0x00,0x00,0x0D,0x49,0x48,0x44,0x52,
|
0x00,0x00,0x00,0x0D,0x49,0x48,0x44,0x52,
|
||||||
|
|
@ -19,14 +17,11 @@ function loadSampleImage(ext: string): Buffer {
|
||||||
]);
|
]);
|
||||||
case "jpg":
|
case "jpg":
|
||||||
case "jpeg":
|
case "jpeg":
|
||||||
// 1x1 JPEG (valid minimal JPEG header)
|
|
||||||
return Buffer.from([
|
return Buffer.from([
|
||||||
0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x00,0x48,0x00,0x48,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x03,0x02,0x02,0x02,0x02,0x02,0x03,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x04,0x06,0x04,0x04,0x04,0x04,0x04,0x08,0x06,0x06,0x05,0x06,0x09,0x08,0x0a,0x0a,0x09,0x08,0x09,0x09,0x0a,0x0c,0x0f,0x0c,0x0a,0x0b,0x0e,0x0b,0x09,0x09,0x0d,0x11,0x0d,0x0e,0x0f,0x10,0x10,0x11,0x10,0x0a,0x0c,0x12,0x13,0x12,0x10,0x13,0x0f,0x10,0x10,0x10,0xff,0xc9,0x00,0x0b,0x08,0x00,0x01,0x00,0x01,0x01,0x01,0x11,0x00,0xff,0xcc,0x00,0x06,0x00,0x10,0x10,0x05,0xff,0xda,0x00,0x08,0x01,0x01,0x00,0x00,0x3f,0x00,0xd2,0xcf,0x20,0xff,0xd9
|
0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x00,0x48,0x00,0x48,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x03,0x02,0x02,0x02,0x02,0x02,0x03,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x04,0x06,0x04,0x04,0x04,0x04,0x04,0x08,0x06,0x06,0x05,0x06,0x09,0x08,0x0a,0x0a,0x09,0x08,0x09,0x09,0x0a,0x0c,0x0f,0x0c,0x0a,0x0b,0x0e,0x0b,0x09,0x09,0x0d,0x11,0x0d,0x0e,0x0f,0x10,0x10,0x11,0x10,0x0a,0x0c,0x12,0x13,0x12,0x10,0x13,0x0f,0x10,0x10,0x10,0xff,0xc9,0x00,0x0b,0x08,0x00,0x01,0x00,0x01,0x01,0x01,0x11,0x00,0xff,0xcc,0x00,0x06,0x00,0x10,0x10,0x05,0xff,0xda,0x00,0x08,0x01,0x01,0x00,0x00,0x3f,0x00,0xd2,0xcf,0x20,0xff,0xd9
|
||||||
]);
|
]);
|
||||||
case "webp":
|
case "webp":
|
||||||
// 1x1 WebP
|
|
||||||
return Buffer.from(
|
return Buffer.from(
|
||||||
|
|
||||||
[82,73,70,70,64,0,0,0,87,69,66,80,86,80,56,88,10,0,0,0,16,0,0,0,0,0,0,0,0,0,65,76,80,72,2,0,0,0,0,0,86,80,56,32,24,0,0,0,48,1,0,157,1,42,1,0,1,0,1,64,38,37,164,0,3,112,0,254,253,54,104,0]
|
[82,73,70,70,64,0,0,0,87,69,66,80,86,80,56,88,10,0,0,0,16,0,0,0,0,0,0,0,0,0,65,76,80,72,2,0,0,0,0,0,86,80,56,32,24,0,0,0,48,1,0,157,1,42,1,0,1,0,1,64,38,37,164,0,3,112,0,254,253,54,104,0]
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
@ -48,12 +43,11 @@ test("ImageOptimization returns buffer for supported types", async () => {
|
||||||
|
|
||||||
test("ImageOptimization returns original buffer if optimized is larger", async () => {
|
test("ImageOptimization returns original buffer if optimized is larger", async () => {
|
||||||
const plugin = new ImageOptimization();
|
const plugin = new ImageOptimization();
|
||||||
// Simulate a case where optimized buffer is larger
|
|
||||||
const buf = Buffer.from([1, 2, 3, 4, 5]);
|
const buf = Buffer.from([1, 2, 3, 4, 5]);
|
||||||
// Patch sharp to return a larger buffer
|
|
||||||
plugin.logging = false;
|
plugin.logging = false;
|
||||||
plugin.rewriteFile = async (file) => {
|
plugin.rewriteFile = async (file) => {
|
||||||
// Simulate optimization making buffer larger
|
|
||||||
const optimized = Buffer.concat([file, Buffer.from([6, 7, 8, 9, 10])]);
|
const optimized = Buffer.concat([file, Buffer.from([6, 7, 8, 9, 10])]);
|
||||||
if (file.length < optimized.length) {
|
if (file.length < optimized.length) {
|
||||||
return file;
|
return file;
|
||||||
|
|
@ -69,7 +63,7 @@ test("ImageOptimization logs when skipping optimization", async () => {
|
||||||
let logged = false;
|
let logged = false;
|
||||||
const origLog = console.log;
|
const origLog = console.log;
|
||||||
console.log = () => { logged = true; };
|
console.log = () => { logged = true; };
|
||||||
// Simulate buffer larger after optimization
|
|
||||||
const buf = Buffer.from([1, 2, 3]);
|
const buf = Buffer.from([1, 2, 3]);
|
||||||
plugin.rewriteFile = async (file) => {
|
plugin.rewriteFile = async (file) => {
|
||||||
const optimized = Buffer.concat([file, Buffer.from([4, 5, 6])]);
|
const optimized = Buffer.concat([file, Buffer.from([4, 5, 6])]);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { expect, test } from "bun:test";
|
import { expect, test } from "bun:test";
|
||||||
import MarkdownCompiler from "../markdown-compiler";
|
import MarkdownCompiler from "../markdown-compiler";
|
||||||
|
|
||||||
// Mock marked and parseMetadata for isolated testing
|
|
||||||
const mockMarked = {
|
const mockMarked = {
|
||||||
parse: (text: string) => `<p>${text}</p>`,
|
parse: (text: string) => `<p>${text}</p>`,
|
||||||
};
|
};
|
||||||
|
|
@ -12,7 +11,6 @@ const mockParseMetadata = (file: string) => {
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Patch dependencies
|
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
MarkdownCompiler.prototype["marked"] = mockMarked;
|
MarkdownCompiler.prototype["marked"] = mockMarked;
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
|
|
@ -21,7 +19,7 @@ MarkdownCompiler.prototype["parseMetadata"] = mockParseMetadata;
|
||||||
test("MarkdownCompiler compiles markdown to HTML", async () => {
|
test("MarkdownCompiler compiles markdown to HTML", async () => {
|
||||||
const plugin = new MarkdownCompiler();
|
const plugin = new MarkdownCompiler();
|
||||||
const input = "# Hello World";
|
const input = "# Hello World";
|
||||||
// Simulate marked.parse
|
|
||||||
const output = await plugin.rewriteFile(input, "test.md");
|
const output = await plugin.rewriteFile(input, "test.md");
|
||||||
expect(typeof output).toBe("string");
|
expect(typeof output).toBe("string");
|
||||||
expect(output).toContain("Hello World");
|
expect(output).toContain("Hello World");
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ author = John Doe
|
||||||
`;
|
`;
|
||||||
const metadata = parseMetadata(input);
|
const metadata = parseMetadata(input);
|
||||||
expect(metadata).toEqual({ title: "My Title", author: "John Doe" });
|
expect(metadata).toEqual({ title: "My Title", author: "John Doe" });
|
||||||
|
expect(metadata).toEqual({ title: "My Title", author: "John Doe" });
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("parseMetadata returns undefined if no metadata block", () => {
|
test("parseMetadata returns undefined if no metadata block", () => {
|
||||||
|
|
@ -26,7 +28,9 @@ description = Sample file
|
||||||
`;
|
`;
|
||||||
const plugin = new MarkdownMetadataGenerator();
|
const plugin = new MarkdownMetadataGenerator();
|
||||||
const output = await plugin.rewriteFile(input, "test.md");
|
const output = await plugin.rewriteFile(input, "test.md");
|
||||||
expect(output).toBe(JSON.stringify({ title: "Hello World", description: "Sample file" }));
|
expect(output).toBe(
|
||||||
|
JSON.stringify({ title: "Hello World", description: "Sample file" }),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("MarkdownMetadataGenerator returns undefined if no metadata", async () => {
|
test("MarkdownMetadataGenerator returns undefined if no metadata", async () => {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { expect, test } from "bun:test";
|
import { expect, test } from "bun:test";
|
||||||
import PostCSS from "../postcss";
|
import PostCSS from "../postcss";
|
||||||
|
|
||||||
// Dummy PostCSS plugin that uppercases all CSS
|
|
||||||
function uppercasePlugin() {
|
function uppercasePlugin() {
|
||||||
return {
|
return {
|
||||||
postcssPlugin: "uppercase",
|
postcssPlugin: "uppercase",
|
||||||
|
|
@ -10,7 +9,7 @@ function uppercasePlugin() {
|
||||||
decl.value = decl.value.toUpperCase();
|
decl.value = decl.value.toUpperCase();
|
||||||
decl.prop = decl.prop.toUpperCase();
|
decl.prop = decl.prop.toUpperCase();
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
uppercasePlugin.postcss = true;
|
uppercasePlugin.postcss = true;
|
||||||
|
|
@ -30,7 +29,6 @@ test("PostCSS returns unchanged CSS if no plugins", async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("PostCSS handles multiple plugins", async () => {
|
test("PostCSS handles multiple plugins", async () => {
|
||||||
// Plugin to replace 'red' with 'green'
|
|
||||||
function replaceRedPlugin() {
|
function replaceRedPlugin() {
|
||||||
return {
|
return {
|
||||||
postcssPlugin: "replace-red",
|
postcssPlugin: "replace-red",
|
||||||
|
|
@ -38,7 +36,7 @@ test("PostCSS handles multiple plugins", async () => {
|
||||||
root.walkDecls((decl: any) => {
|
root.walkDecls((decl: any) => {
|
||||||
decl.value = decl.value.replace(/red/g, "green");
|
decl.value = decl.value.replace(/red/g, "green");
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
replaceRedPlugin.postcss = true;
|
replaceRedPlugin.postcss = true;
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
import { expect, test } from "bun:test";
|
import { expect, test } from "bun:test";
|
||||||
import TSCompiler from "../ts-compiler";
|
import TSCompiler from "../ts-compiler";
|
||||||
|
|
||||||
// Mock esbuild for isolated testing
|
|
||||||
const mockBuild = async (options: any) => {
|
const mockBuild = async (options: any) => {
|
||||||
// Simulate successful build with dummy JS output
|
|
||||||
return {
|
return {
|
||||||
errors: [],
|
errors: [],
|
||||||
outputFiles: [{ contents: Buffer.from("console.log('hello world');") }],
|
outputFiles: [{ contents: Buffer.from("console.log('hello world');") }],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Patch esbuild in TSCompiler for testing
|
|
||||||
TSCompiler.prototype["esbuildOptions"] = {};
|
TSCompiler.prototype["esbuildOptions"] = {};
|
||||||
TSCompiler.prototype["rewriteFile"] = async function (file: string, filePath: string) {
|
TSCompiler.prototype["rewriteFile"] = async function (
|
||||||
|
file: string,
|
||||||
|
filePath: string,
|
||||||
|
) {
|
||||||
let result;
|
let result;
|
||||||
try {
|
try {
|
||||||
result = await mockBuild({
|
result = await mockBuild({
|
||||||
|
|
@ -46,7 +46,6 @@ test("TSCompiler compiles TypeScript to JavaScript", async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("TSCompiler returns undefined on build error", async () => {
|
test("TSCompiler returns undefined on build error", async () => {
|
||||||
// Simulate error
|
|
||||||
TSCompiler.prototype["rewriteFile"] = async function () {
|
TSCompiler.prototype["rewriteFile"] = async function () {
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { Plugin } from "..";
|
||||||
|
|
||||||
export default class CompileTimeJS extends Plugin {
|
export default class CompileTimeJS extends Plugin {
|
||||||
name = "compile-time-js";
|
name = "compile-time-js";
|
||||||
rewriteTriggers = ["html", "*"]
|
rewriteTriggers = ["html", "*"];
|
||||||
longLasting = false;
|
longLasting = false;
|
||||||
build = undefined;
|
build = undefined;
|
||||||
|
|
||||||
|
|
@ -20,10 +20,9 @@ export default class CompileTimeJS extends Plugin {
|
||||||
const expr = m[1];
|
const expr = m[1];
|
||||||
const after = input.slice(m.index + m[0].length);
|
const after = input.slice(m.index + m[0].length);
|
||||||
|
|
||||||
const result = eval(expr); // You can replace this with Function() for sandboxing
|
const result = eval(expr);
|
||||||
input = before + result + after;
|
input = before + result + after;
|
||||||
|
|
||||||
// Reset regex lastIndex since we changed the string
|
|
||||||
regex.lastIndex = 0;
|
regex.lastIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,12 @@ export default class DevPlugin extends Plugin {
|
||||||
renameTo = undefined;
|
renameTo = undefined;
|
||||||
longLasting = true;
|
longLasting = true;
|
||||||
server!: Server;
|
server!: Server;
|
||||||
|
watcher!: fs.FSWatcher;
|
||||||
allConnections: ServerWebSocket<number>[] = [];
|
allConnections: ServerWebSocket<number>[] = [];
|
||||||
|
|
||||||
// please never set "startEverything" to false, it's meant to be used only in tests
|
constructor(sssg: SSSG, headers: Record<string, string>, port = 8080) {
|
||||||
constructor(sssg: SSSG, headers: Record<string, string>, port = 8080, startEverything = true) {
|
|
||||||
super();
|
super();
|
||||||
if (startEverything) {
|
this.watcher = fs.watch(
|
||||||
fs.watch(
|
|
||||||
sssg.inputFolder,
|
sssg.inputFolder,
|
||||||
{
|
{
|
||||||
recursive: true,
|
recursive: true,
|
||||||
|
|
@ -28,7 +27,7 @@ export default class DevPlugin extends Plugin {
|
||||||
console.log("[dev] Noticed update in " + f + ", of type " + e + ".");
|
console.log("[dev] Noticed update in " + f + ", of type " + e + ".");
|
||||||
this.allConnections.forEach((z) => z.send("refresh"));
|
this.allConnections.forEach((z) => z.send("refresh"));
|
||||||
await sssg.build();
|
await sssg.build();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this.server = Bun.serve<number>({
|
this.server = Bun.serve<number>({
|
||||||
|
|
@ -60,19 +59,19 @@ export default class DevPlugin extends Plugin {
|
||||||
const type = fsPath.split(".").at(-1);
|
const type = fsPath.split(".").at(-1);
|
||||||
if (!type) return;
|
if (!type) return;
|
||||||
if (type == "html") {
|
if (type == "html") {
|
||||||
|
rawFile = rawFile
|
||||||
rawFile = rawFile.toString().replace(
|
.toString()
|
||||||
"<head>",
|
.replace("<head>", `<head><script>${script}</script>`);
|
||||||
`<head><script>${script}</script>`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return new Response(rawFile, {
|
return new Response(rawFile, {
|
||||||
headers: {
|
headers: {
|
||||||
"Cache-Control": "no-cache, no-store, must-revalidate",
|
"Cache-Control": "no-cache, no-store, must-revalidate",
|
||||||
"Pragma": "no-cache",
|
Pragma: "no-cache",
|
||||||
"Expires": "0",
|
Expires: "0",
|
||||||
"Content-Type": (mime.lookup(type) || "application/octet-stream") + "; charset=utf-8",
|
"Content-Type":
|
||||||
...headers
|
(mime.lookup(type) || "application/octet-stream") +
|
||||||
|
"; charset=utf-8",
|
||||||
|
...headers,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
@ -82,17 +81,16 @@ export default class DevPlugin extends Plugin {
|
||||||
|
|
||||||
this.allConnections.push(ws);
|
this.allConnections.push(ws);
|
||||||
},
|
},
|
||||||
message(ws, message) { },
|
message(ws, message) {},
|
||||||
close: (ws) => {
|
close: (ws) => {
|
||||||
this.allConnections = this.allConnections.filter(
|
this.allConnections = this.allConnections.filter(
|
||||||
(z) => z.data != ws.data
|
(z) => z.data != ws.data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
port: port,
|
port: port,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
async rewriteFile(file: string, filePath: string) {
|
async rewriteFile(file: string, filePath: string) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ export default class ImageOptimization extends Plugin {
|
||||||
nonOptimized.byteLength +
|
nonOptimized.byteLength +
|
||||||
"B) optimized was " +
|
"B) optimized was " +
|
||||||
data.byteLength +
|
data.byteLength +
|
||||||
"B. It has been skipped."
|
"B. It has been skipped.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
data = nonOptimized;
|
data = nonOptimized;
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,17 @@ export default class MarkdownCompiler extends Plugin {
|
||||||
build: undefined;
|
build: undefined;
|
||||||
|
|
||||||
name = "markdown-compiler";
|
name = "markdown-compiler";
|
||||||
rewriteTriggers = ["md"]
|
rewriteTriggers = ["md"];
|
||||||
renameTo = "html"
|
renameTo = "html";
|
||||||
longLasting = false;
|
longLasting = false;
|
||||||
|
|
||||||
async rewriteFile(file: string, filePath: string) {
|
async rewriteFile(file: string, filePath: string) {
|
||||||
let text = file;
|
let text = file;
|
||||||
const metadata = parseMetadata(text);
|
const metadata = parseMetadata(text);
|
||||||
if(metadata) {
|
if (metadata) {
|
||||||
let textSplit = text.split('\n');
|
let textSplit = text.split("\n");
|
||||||
textSplit.splice(0, Object.keys(metadata).length);
|
textSplit.splice(0, Object.keys(metadata).length);
|
||||||
textSplit.unshift(metadata.title)
|
textSplit.unshift(metadata.title);
|
||||||
text = textSplit.join("\n");
|
text = textSplit.join("\n");
|
||||||
}
|
}
|
||||||
return await marked.parse(text);
|
return await marked.parse(text);
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ export default class PostCSS extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
async rewriteFile(file: string) {
|
async rewriteFile(file: string) {
|
||||||
const data = await postcss(this.plugins).process(file, {from: undefined});
|
const data = await postcss(this.plugins).process(file, { from: undefined });
|
||||||
return data.css;
|
return data.css;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ export default class TSCompiler extends Plugin {
|
||||||
bundle: true,
|
bundle: true,
|
||||||
outdir: "out",
|
outdir: "out",
|
||||||
minify: this.minify,
|
minify: this.minify,
|
||||||
...this.esbuildOptions
|
...this.esbuildOptions,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue