@kaathewise/ssg 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +7 -12
- package/dist/config.d.ts.map +1 -1
- package/dist/render.d.ts +1 -4
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +8 -4
- package/dist/router.d.ts +22 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +90 -0
- package/dist/run.d.ts +1 -1
- package/dist/run.js +7 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +54 -73
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +13 -0
- package/package.json +5 -5
- package/src/run.ts +0 -45
package/dist/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAIzC,wBAAsB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBzD"}
|
package/dist/build.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import * as fs from "node:fs/promises";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { Glob, write } from "bun";
|
|
4
3
|
import { renderAll } from "./render.js";
|
|
5
|
-
|
|
4
|
+
import { walk } from "./utils.js";
|
|
6
5
|
export async function build(config) {
|
|
7
6
|
const pages = [];
|
|
8
|
-
for await (const
|
|
9
|
-
const
|
|
10
|
-
const p = await renderAll(modulePath, config.pagesDir);
|
|
7
|
+
for await (const filePath of walk(config.pagesDir)) {
|
|
8
|
+
const p = await renderAll(filePath, config.pagesDir);
|
|
11
9
|
pages.push(...p);
|
|
12
10
|
}
|
|
13
11
|
await fs.rm(config.outputDir, { recursive: true, force: true });
|
|
@@ -15,13 +13,10 @@ export async function build(config) {
|
|
|
15
13
|
for (const page of pages) {
|
|
16
14
|
const destPath = path.join(config.outputDir, page.path);
|
|
17
15
|
const dir = path.dirname(destPath);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
const file = Bun.file(destPath);
|
|
24
|
-
await write(file, page.src);
|
|
16
|
+
await fs.mkdir(path.dirname(destPath), {
|
|
17
|
+
recursive: true,
|
|
18
|
+
});
|
|
19
|
+
await fs.writeFile(destPath, page.src);
|
|
25
20
|
}
|
|
26
21
|
if (config.assetDir) {
|
|
27
22
|
await fs.cp(config.assetDir, config.outputDir, {
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,MAAM,GAAG;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE;IACrC,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;CACb,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,MAAM,GAAG;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE;IACrC,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;CACb,GAAG,MAAM,CAaT"}
|
package/dist/render.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
[name: string]: string;
|
|
3
|
-
}
|
|
1
|
+
import type { Params } from "./router.ts";
|
|
4
2
|
export type Page = {
|
|
5
3
|
path: string;
|
|
6
4
|
src: string;
|
|
@@ -8,5 +6,4 @@ export type Page = {
|
|
|
8
6
|
};
|
|
9
7
|
export declare function render(modulePath: string, pagesDir: string, params?: Params): Promise<Page>;
|
|
10
8
|
export declare function renderAll(modulePath: string, pagesDir: string): Promise<Page[]>;
|
|
11
|
-
export {};
|
|
12
9
|
//# sourceMappingURL=render.d.ts.map
|
package/dist/render.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,MAAM,MAAM,IAAI,GAAG;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B,CAAA;AAED,wBAAsB,MAAM,CAC3B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,MAAW,GACjB,OAAO,CAAC,IAAI,CAAC,CAiCf;AAED,wBAAsB,SAAS,CAC9B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,EAAE,CAAC,CAgBjB"}
|
package/dist/render.js
CHANGED
|
@@ -53,10 +53,14 @@ export async function renderAll(modulePath, pagesDir) {
|
|
|
53
53
|
function substituteParams(inputPath, params) {
|
|
54
54
|
let path = inputPath;
|
|
55
55
|
for (const [key, value] of Object.entries(params)) {
|
|
56
|
-
const single =
|
|
57
|
-
const multiple =
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
const single = `:${key}`;
|
|
57
|
+
const multiple = `*${key}`;
|
|
58
|
+
if (typeof value === "string") {
|
|
59
|
+
path = path.replace(single, value);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
path = path.replace(multiple, value.join("/"));
|
|
63
|
+
}
|
|
60
64
|
}
|
|
61
65
|
path = path.replace(/\.tsx?$/, "");
|
|
62
66
|
return path;
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type Match = {
|
|
2
|
+
filePath: string;
|
|
3
|
+
params: Params;
|
|
4
|
+
};
|
|
5
|
+
export type Params = Record<string, string | string[]>;
|
|
6
|
+
export declare class Router {
|
|
7
|
+
#private;
|
|
8
|
+
constructor(root: string, paths: Path[]);
|
|
9
|
+
static new(dir: string): Promise<Router>;
|
|
10
|
+
match(pathname: string): Match | null;
|
|
11
|
+
reload(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
type Path = {
|
|
14
|
+
filePath: string;
|
|
15
|
+
fragments: Fragment[];
|
|
16
|
+
};
|
|
17
|
+
type Fragment = {
|
|
18
|
+
kind: "literal" | "segment" | "repeat";
|
|
19
|
+
value: string;
|
|
20
|
+
};
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,KAAK,GAAG;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;AAEtD,qBAAa,MAAM;;gBAIN,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;WAK1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW9C,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI;IAe/B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B;AAED,KAAK,IAAI,GAAG;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,QAAQ,EAAE,CAAA;CACrB,CAAA;AA+CD,KAAK,QAAQ,GAAG;IACf,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAA;IACtC,KAAK,EAAE,MAAM,CAAA;CACb,CAAA"}
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { walk } from "./utils.js";
|
|
3
|
+
export class Router {
|
|
4
|
+
#root;
|
|
5
|
+
#paths;
|
|
6
|
+
constructor(root, paths) {
|
|
7
|
+
this.#root = root;
|
|
8
|
+
this.#paths = paths;
|
|
9
|
+
}
|
|
10
|
+
static async new(dir) {
|
|
11
|
+
const paths = [];
|
|
12
|
+
for await (const pagePath of walk(dir)) {
|
|
13
|
+
const rel = path.relative(dir, pagePath);
|
|
14
|
+
paths.push(toPath(rel));
|
|
15
|
+
}
|
|
16
|
+
return new Router(dir, paths);
|
|
17
|
+
}
|
|
18
|
+
match(pathname) {
|
|
19
|
+
for (const pagePath of this.#paths) {
|
|
20
|
+
const match = matchPath(pagePath, pathname);
|
|
21
|
+
if (match) {
|
|
22
|
+
match.filePath = path.join(this.#root, match.filePath);
|
|
23
|
+
return match;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
async reload() {
|
|
29
|
+
const replacement = await Router.new(this.#root);
|
|
30
|
+
this.#paths = replacement.#paths;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function toPath(pagePath) {
|
|
34
|
+
return {
|
|
35
|
+
filePath: pagePath,
|
|
36
|
+
fragments: toFragments(pagePath),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function matchPath(pagePath, pathname) {
|
|
40
|
+
const params = {};
|
|
41
|
+
const parts = pathname.split("/").slice(1);
|
|
42
|
+
for (const [i, fragment] of pagePath.fragments.entries()) {
|
|
43
|
+
const part = parts[i];
|
|
44
|
+
if (!part) {
|
|
45
|
+
if (fragment.value === "index") {
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
switch (fragment.kind) {
|
|
53
|
+
case "literal": {
|
|
54
|
+
if (fragment.value !== part) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
case "segment": {
|
|
60
|
+
params[fragment.value] = part;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case "repeat": {
|
|
64
|
+
params[fragment.value] = parts.slice(i);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
filePath: pagePath.filePath,
|
|
71
|
+
params,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function toFragments(pagePath) {
|
|
75
|
+
const barePath = pagePath.replace(/\.tsx?/, "");
|
|
76
|
+
const pieces = barePath.split("/");
|
|
77
|
+
const out = [];
|
|
78
|
+
for (const piece of pieces) {
|
|
79
|
+
if (piece.startsWith(":")) {
|
|
80
|
+
out.push({ kind: "segment", value: piece.slice(1) });
|
|
81
|
+
}
|
|
82
|
+
else if (piece.startsWith("*")) {
|
|
83
|
+
out.push({ kind: "repeat", value: piece.slice(1) });
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
out.push({ kind: "literal", value: piece });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
package/dist/run.d.ts
CHANGED
package/dist/run.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
3
3
|
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
4
4
|
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
@@ -7,8 +7,10 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
7
7
|
}
|
|
8
8
|
return path;
|
|
9
9
|
};
|
|
10
|
+
import console from "node:console";
|
|
10
11
|
import * as fs from "node:fs/promises";
|
|
11
12
|
import * as path from "node:path";
|
|
13
|
+
import process from "node:process";
|
|
12
14
|
import { build, serve } from "./index.js";
|
|
13
15
|
const CONFIG_PATH = "ssg.config.ts";
|
|
14
16
|
const HELP = `Usage: ssg <command>
|
|
@@ -19,7 +21,10 @@ Commands:
|
|
|
19
21
|
`;
|
|
20
22
|
const args = process.argv.slice(2);
|
|
21
23
|
const configPath = path.resolve(CONFIG_PATH);
|
|
22
|
-
|
|
24
|
+
try {
|
|
25
|
+
fs.access(configPath);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
23
28
|
console.warn("Configuration file not found");
|
|
24
29
|
process.exit(10);
|
|
25
30
|
}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAMzC,wBAAsB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCzD"}
|
package/dist/server.js
CHANGED
|
@@ -1,82 +1,75 @@
|
|
|
1
1
|
import * as fs from "node:fs/promises";
|
|
2
2
|
import { watch } from "node:fs/promises";
|
|
3
|
+
import http from "node:http";
|
|
3
4
|
import * as path from "node:path";
|
|
5
|
+
import url from "node:url";
|
|
4
6
|
import { render } from "./render.js";
|
|
7
|
+
import { Router } from "./router.js";
|
|
5
8
|
const EVENT_PATH = "/__ssg_dev_sse";
|
|
6
9
|
export async function serve(config) {
|
|
7
10
|
const clients = new Set();
|
|
8
|
-
const router =
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (asset) {
|
|
27
|
-
return asset;
|
|
28
|
-
}
|
|
29
|
-
console.warn(`Path '${url.pathname}' not found`);
|
|
30
|
-
return new Response("Page or file not found", {
|
|
31
|
-
status: 404,
|
|
32
|
-
});
|
|
33
|
-
},
|
|
11
|
+
const router = await Router.new(config.pagesDir);
|
|
12
|
+
const server = http.createServer(async (request, response) => {
|
|
13
|
+
const rUrl = new url.URL(request.url ?? "/", "http://localhost");
|
|
14
|
+
if (rUrl.pathname === EVENT_PATH) {
|
|
15
|
+
createStream(response, clients);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const route = router.match(rUrl.pathname);
|
|
19
|
+
if (route) {
|
|
20
|
+
await serveHtml(response, route, config.pagesDir);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (await fetchStaticFile(response, rUrl, config.assetDir)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
console.warn(`Path '${rUrl.pathname}' not found`);
|
|
27
|
+
response.writeHead(404);
|
|
28
|
+
response.end("Page or file not found");
|
|
34
29
|
});
|
|
30
|
+
server.listen(config.port);
|
|
35
31
|
console.log(`Listening on :${config.port}`);
|
|
36
32
|
const watcher = watch(config.sourceDir, { recursive: true });
|
|
37
33
|
for await (const _ of watcher) {
|
|
38
|
-
router.reload();
|
|
39
|
-
clearCache(config.sourceDir);
|
|
34
|
+
await router.reload();
|
|
40
35
|
for (const client of clients) {
|
|
41
|
-
client.
|
|
36
|
+
client.write("data: RELOAD\n\n");
|
|
42
37
|
}
|
|
43
38
|
}
|
|
44
39
|
}
|
|
45
|
-
function createStream(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// aspartik/website for some reason, breaking the check.
|
|
51
|
-
// biome-ignore lint/suspicious/noExplicitAny: above
|
|
52
|
-
const signal = request.signal;
|
|
53
|
-
signal.addEventListener("abort", () => {
|
|
54
|
-
controller.close();
|
|
55
|
-
clients.delete(controller);
|
|
56
|
-
});
|
|
57
|
-
},
|
|
40
|
+
function createStream(response, clients) {
|
|
41
|
+
response.writeHead(200, {
|
|
42
|
+
"Content-Type": "text/event-stream",
|
|
43
|
+
"Cache-Control": "no-cache",
|
|
44
|
+
Connection: "keep-alive",
|
|
58
45
|
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
},
|
|
46
|
+
clients.add(response);
|
|
47
|
+
response.on("close", () => {
|
|
48
|
+
clients.delete(response);
|
|
49
|
+
response.end();
|
|
64
50
|
});
|
|
65
51
|
}
|
|
66
|
-
async function fetchStaticFile(url, assetDir) {
|
|
52
|
+
async function fetchStaticFile(response, url, assetDir) {
|
|
67
53
|
if (!assetDir) {
|
|
68
|
-
return
|
|
54
|
+
return false;
|
|
69
55
|
}
|
|
70
56
|
let assetPath = path.join(assetDir, url.pathname.slice(1));
|
|
71
57
|
assetPath = path.resolve(assetPath);
|
|
72
58
|
if (!assetPath.startsWith(assetDir)) {
|
|
73
|
-
|
|
59
|
+
response.writeHead(403);
|
|
60
|
+
response.end("Tried to get a file outside of the asset directory");
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const contents = await fs.readFile(assetPath);
|
|
65
|
+
response.writeHead(200);
|
|
66
|
+
response.end(contents);
|
|
67
|
+
return true;
|
|
74
68
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return
|
|
69
|
+
catch {
|
|
70
|
+
// the file doesn't exist
|
|
71
|
+
return false;
|
|
78
72
|
}
|
|
79
|
-
return new Response(Bun.file(assetPath));
|
|
80
73
|
}
|
|
81
74
|
const RELOAD_SCRIPT = `
|
|
82
75
|
<script type="module">
|
|
@@ -89,25 +82,13 @@ const RELOAD_SCRIPT = `
|
|
|
89
82
|
window.addEventListener("beforeunload", () => sse.close())
|
|
90
83
|
</script>
|
|
91
84
|
`;
|
|
92
|
-
async function
|
|
85
|
+
async function serveHtml(response, route, pagesDir) {
|
|
93
86
|
const page = await render(route.filePath, pagesDir, route.params);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
"Content-Type": page.contentType ?? "text/html",
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
return new HTMLRewriter()
|
|
100
|
-
.onDocument({
|
|
101
|
-
end: (el) => {
|
|
102
|
-
el.append(RELOAD_SCRIPT, { html: true });
|
|
103
|
-
},
|
|
104
|
-
})
|
|
105
|
-
.transform(response);
|
|
106
|
-
}
|
|
107
|
-
function clearCache(prefix) {
|
|
108
|
-
for (const path in import.meta.require.cache) {
|
|
109
|
-
if (path.startsWith(prefix)) {
|
|
110
|
-
delete import.meta.require.cache[path];
|
|
111
|
-
}
|
|
87
|
+
if (page.contentType === "text/html" || !page.contentType) {
|
|
88
|
+
page.src += RELOAD_SCRIPT;
|
|
112
89
|
}
|
|
90
|
+
response.writeHead(200, {
|
|
91
|
+
"Content-Type": page.contentType ?? "text/html",
|
|
92
|
+
});
|
|
93
|
+
response.end(page.src);
|
|
113
94
|
}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,wBAAuB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAS/D"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export async function* walk(dir) {
|
|
4
|
+
for await (const d of await fs.opendir(dir)) {
|
|
5
|
+
const entry = path.join(dir, d.name);
|
|
6
|
+
if (d.isDirectory()) {
|
|
7
|
+
yield* walk(entry);
|
|
8
|
+
}
|
|
9
|
+
else if (d.isFile()) {
|
|
10
|
+
yield entry;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaathewise/ssg",
|
|
3
3
|
"description": "JSX static site generator",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.7.1",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"author": "Andrej Kolčin",
|
|
7
7
|
"type": "module",
|
|
@@ -11,18 +11,18 @@
|
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"check": "biome check && tsc --noEmit",
|
|
14
|
-
"build": "tsc
|
|
14
|
+
"build": "tsc"
|
|
15
15
|
},
|
|
16
|
-
"main": "dist/index.
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
17
18
|
"bin": {
|
|
18
|
-
"ssg": "
|
|
19
|
+
"ssg": "dist/run.js"
|
|
19
20
|
},
|
|
20
21
|
"files": [
|
|
21
22
|
"dist"
|
|
22
23
|
],
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"@biomejs/biome": "^2.2.3",
|
|
25
|
-
"@types/bun": "^1.2.21",
|
|
26
26
|
"@types/node": "^24.3.1",
|
|
27
27
|
"typescript": "^5.9.2",
|
|
28
28
|
"typescript-language-server": "^4.4.0"
|
package/src/run.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
import * as fs from "node:fs/promises"
|
|
4
|
-
import * as path from "node:path"
|
|
5
|
-
import { build, type Config, serve } from "./index.ts"
|
|
6
|
-
|
|
7
|
-
const CONFIG_PATH = "ssg.config.ts"
|
|
8
|
-
const HELP = `Usage: ssg <command>
|
|
9
|
-
|
|
10
|
-
Commands:
|
|
11
|
-
build: build the website
|
|
12
|
-
dev: start a hot-reloading development server
|
|
13
|
-
`
|
|
14
|
-
|
|
15
|
-
const args = process.argv.slice(2)
|
|
16
|
-
|
|
17
|
-
const configPath = path.resolve(CONFIG_PATH)
|
|
18
|
-
if (!(await fs.exists(configPath))) {
|
|
19
|
-
console.warn("Configuration file not found")
|
|
20
|
-
process.exit(10)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const configModule = await import(configPath)
|
|
24
|
-
const config = configModule.default as Config
|
|
25
|
-
|
|
26
|
-
switch (args[0]) {
|
|
27
|
-
case "build": {
|
|
28
|
-
await build(config)
|
|
29
|
-
break
|
|
30
|
-
}
|
|
31
|
-
case "dev": {
|
|
32
|
-
await serve(config)
|
|
33
|
-
break
|
|
34
|
-
}
|
|
35
|
-
case undefined: {
|
|
36
|
-
console.log(HELP)
|
|
37
|
-
break
|
|
38
|
-
}
|
|
39
|
-
default: {
|
|
40
|
-
console.log(
|
|
41
|
-
`The command must be either 'build' or 'dev', got ${args[0]}`,
|
|
42
|
-
)
|
|
43
|
-
process.exit(11)
|
|
44
|
-
}
|
|
45
|
-
}
|