@kaathewise/ssg 0.9.1 → 0.10.0

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.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import * as fs from "node:fs/promises";
2
2
  import * as path from "node:path";
3
- import { renderAll } from "./render.js";
3
+ import { makeAllPages, render } from "./render.js";
4
4
  import { walk } from "./utils.js";
5
5
  export async function build(config) {
6
6
  const pages = [];
7
7
  for await (const modulePath of walk(config.routesDir)) {
8
- const p = await renderAll(modulePath, config);
8
+ const p = await makeAllPages(modulePath, config);
9
9
  pages.push(...p);
10
10
  }
11
11
  await fs.rm(config.outputDir, { recursive: true, force: true });
@@ -15,7 +15,7 @@ export async function build(config) {
15
15
  await fs.mkdir(path.dirname(destPath), {
16
16
  recursive: true,
17
17
  });
18
- await fs.writeFile(destPath, page.src);
18
+ await fs.writeFile(destPath, render(page));
19
19
  }
20
20
  if (config.assetDir) {
21
21
  await fs.cp(config.assetDir, config.outputDir, {
package/dist/config.d.ts CHANGED
@@ -13,6 +13,7 @@ export declare class Config {
13
13
  loaders: Loader[];
14
14
  constructor(options: ConfigOptions);
15
15
  getLoader(modulePath: string): Loader | null;
16
+ get scratchDir(): string;
16
17
  }
17
18
  export type Loader = {
18
19
  matcher: RegExp;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,aAAa,GAAG;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAClB,CAAA;AAED,qBAAa,MAAM;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IAEZ,OAAO,EAAE,MAAM,EAAE,CAAA;gBAEL,OAAO,EAAE,aAAa;IAclC,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAQ5C;AAED,MAAM,MAAM,MAAM,GAAG;IACpB,OAAO,EAAE,MAAM,CAAA;CACf,CAAA;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAE3D"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,aAAa,GAAG;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAClB,CAAA;AAED,qBAAa,MAAM;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IAEZ,OAAO,EAAE,MAAM,EAAE,CAAA;gBAEL,OAAO,EAAE,aAAa;IAclC,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAS5C,IAAI,UAAU,IAAI,MAAM,CAEvB;CACD;AAED,MAAM,MAAM,MAAM,GAAG;IACpB,OAAO,EAAE,MAAM,CAAA;CACf,CAAA;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAE3D"}
package/dist/config.js CHANGED
@@ -1,3 +1,4 @@
1
+ import * as fs from "node:fs";
1
2
  import * as path from "node:path";
2
3
  const OUTPUT_DIR = "dist/";
3
4
  const DEFAULT_PORT = 3001;
@@ -14,6 +15,7 @@ export class Config {
14
15
  if (options.assetDir) {
15
16
  this.assetDir = path.resolve(options.assetDir);
16
17
  }
18
+ fs.mkdirSync(this.scratchDir, { recursive: true });
17
19
  this.loaders = options.loaders ?? [];
18
20
  }
19
21
  getLoader(modulePath) {
@@ -24,6 +26,9 @@ export class Config {
24
26
  }
25
27
  return null;
26
28
  }
29
+ get scratchDir() {
30
+ return path.join(this.outputDir, "scratch");
31
+ }
27
32
  }
28
33
  export function defineConfig(options) {
29
34
  return new Config(options);
package/dist/render.d.ts CHANGED
@@ -2,16 +2,19 @@ import type { Config } from "./config.ts";
2
2
  import type { Params } from "./router.ts";
3
3
  export type Page = {
4
4
  path: string;
5
- src: string;
5
+ head: string;
6
+ body: string;
6
7
  contentType: string | null;
7
8
  };
8
9
  export type ArbitraryModule = {
9
- getStaticParams?(): Params[];
10
+ getStaticParams?: (() => Params[]) | (() => Promise<Params[]>);
10
11
  getContentType?(params: Params): string;
11
- default?: ((params: Params) => string) | ((params: Params) => Promise<string>);
12
+ Body: (params: Params) => Promise<string>;
13
+ Head: (params: Params, body: string) => Promise<string>;
12
14
  };
13
- export declare function load(modulePath: string): Promise<ArbitraryModule>;
14
- export declare function render(modulePath: string, params: Params, config: Config): Promise<Page>;
15
- export declare function renderAll(modulePath: string, config: Config): Promise<Page[]>;
15
+ export declare function load(modulePath: string, config: Config): Promise<ArbitraryModule>;
16
+ export declare function makePage(modulePath: string, params: Params, config: Config): Promise<Page>;
17
+ export declare function makeAllPages(modulePath: string, config: Config): Promise<Page[]>;
16
18
  export declare function substituteParams(inputPath: string, params: Params): string;
19
+ export declare function render(page: Page): string;
17
20
  //# sourceMappingURL=render.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,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,MAAM,MAAM,eAAe,GAAG;IAC7B,eAAe,CAAC,IAAI,MAAM,EAAE,CAAA;IAC5B,cAAc,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IACvC,OAAO,CAAC,EACL,CAAC,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,GAC5B,CAAC,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;CACxC,CAAA;AAED,wBAAsB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAGvE;AAED,wBAAsB,MAAM,CAC3B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAkCf;AAED,wBAAsB,SAAS,CAC9B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,EAAE,CAAC,CAgBjB;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAgB1E"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,MAAM,MAAM,IAAI,GAAG;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC7B,eAAe,CAAC,EAAE,CAAC,MAAM,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IAC9D,cAAc,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IACvC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACzC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACvD,CAAA;AAED,wBAAsB,IAAI,CACzB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,eAAe,CAAC,CAe1B;AAED,wBAAsB,QAAQ,CAC7B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED,wBAAsB,YAAY,CACjC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,EAAE,CAAC,CAgBjB;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAgB1E;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAWzC"}
package/dist/render.js CHANGED
@@ -7,51 +7,49 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
7
7
  return path;
8
8
  };
9
9
  import * as path from "node:path";
10
- import { tsImport } from "tsx/esm/api";
11
- export async function load(modulePath) {
12
- const module = tsImport(modulePath, { parentURL: import.meta.url });
10
+ import { rolldown } from "rolldown";
11
+ export async function load(modulePath, config) {
12
+ const bundle = await rolldown({
13
+ input: modulePath,
14
+ external: [/^[./][a-z0-9-_]$/, /^@[a-z0-9-_]\/[a-z0-9-_]$/, /^node:/],
15
+ });
16
+ const chunks = await bundle.write({
17
+ format: "esm",
18
+ dir: config.scratchDir,
19
+ });
20
+ const output = chunks.output[0];
21
+ const outputPath = `${config.scratchDir}/${output.fileName}?t=${Date.now()}`;
22
+ const module = await import(__rewriteRelativeImportExtension(outputPath));
23
+ await bundle.close();
13
24
  return module;
14
25
  }
15
- export async function render(modulePath, params, config) {
16
- const module = await load(modulePath);
26
+ export async function makePage(modulePath, params, config) {
27
+ const module = await load(modulePath, config);
17
28
  let contentType = null;
18
29
  if (module.getContentType) {
19
30
  contentType = module.getContentType(params);
20
31
  }
21
- const def = module.default;
22
- let src;
23
- switch (typeof def) {
24
- case "string": {
25
- src = def;
26
- break;
27
- }
28
- case "function": {
29
- src = await def(params);
30
- break;
31
- }
32
- default: {
33
- throw "`default` must be a string or a function";
34
- }
35
- }
32
+ const body = await module.Body(params);
33
+ const head = await module.Head(params, body);
36
34
  let pagePath = path.relative(config.routesDir, modulePath);
37
35
  pagePath = substituteParams(pagePath, params);
38
36
  pagePath = pagePath.replace(/\.tsx?$/, "");
39
37
  if (pagePath.endsWith("index")) {
40
38
  pagePath += ".html";
41
39
  }
42
- return { path: pagePath, src, contentType };
40
+ return { path: pagePath, head, body, contentType };
43
41
  }
44
- export async function renderAll(modulePath, config) {
45
- const module = await import(__rewriteRelativeImportExtension(modulePath));
42
+ export async function makeAllPages(modulePath, config) {
43
+ const module = await load(modulePath, config);
46
44
  const out = [];
47
- if ("getStaticParams" in module) {
45
+ if (module.getStaticParams) {
48
46
  const paramsList = await module.getStaticParams();
49
47
  for (const params of paramsList) {
50
- out.push(await render(modulePath, params, config));
48
+ out.push(await makePage(modulePath, params, config));
51
49
  }
52
50
  }
53
51
  else {
54
- out.push(await render(modulePath, {}, config));
52
+ out.push(await makePage(modulePath, {}, config));
55
53
  }
56
54
  return out;
57
55
  }
@@ -70,3 +68,15 @@ export function substituteParams(inputPath, params) {
70
68
  path = path.replace(/\.tsx?$/, "");
71
69
  return path;
72
70
  }
71
+ export function render(page) {
72
+ return `<!doctype html>
73
+ <html>
74
+ <head>
75
+ ${page.head}
76
+ </head>
77
+ <body>
78
+ ${page.body}
79
+ </body>
80
+ </html>
81
+ `;
82
+ }
@@ -1 +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;IAe9C,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;AAgED,KAAK,QAAQ,GAAG;IACf,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAA;IACtC,KAAK,EAAE,MAAM,CAAA;CACb,CAAA"}
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;IAe9C,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI;IAY/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;AAgED,KAAK,QAAQ,GAAG;IACf,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAA;IACtC,KAAK,EAAE,MAAM,CAAA;CACb,CAAA"}
@@ -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;AAMzC,wBAAsB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCzD"}
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
@@ -3,7 +3,7 @@ import { watch } from "node:fs/promises";
3
3
  import http from "node:http";
4
4
  import * as path from "node:path";
5
5
  import url from "node:url";
6
- import { render } from "./render.js";
6
+ import { makePage, render } from "./render.js";
7
7
  import { Router } from "./router.js";
8
8
  const EVENT_PATH = "/__ssg_dev_sse";
9
9
  export async function serve(config) {
@@ -30,8 +30,7 @@ export async function serve(config) {
30
30
  server.listen(config.port);
31
31
  console.log(`Listening on :${config.port}`);
32
32
  const watcher = watch(process.cwd(), { recursive: true });
33
- for await (const e of watcher) {
34
- console.log(e);
33
+ for await (const _e of watcher) {
35
34
  await router.reload();
36
35
  for (const client of clients) {
37
36
  client.write("data: RELOAD\n\n");
@@ -85,14 +84,14 @@ const RELOAD_SCRIPT = `
85
84
  `;
86
85
  async function serveHtml(response, route, config) {
87
86
  try {
88
- const page = await render(route.filePath, route.params, config);
87
+ const page = await makePage(route.filePath, route.params, config);
89
88
  if (page.contentType === "text/html" || !page.contentType) {
90
- page.src += RELOAD_SCRIPT;
89
+ page.head += RELOAD_SCRIPT;
91
90
  }
92
91
  response.writeHead(200, {
93
92
  "Content-Type": page.contentType ?? "text/html",
94
93
  });
95
- response.end(page.src);
94
+ response.end(render(page));
96
95
  }
97
96
  catch (err) {
98
97
  response.writeHead(500, { "Content-Type": "text/plain" });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kaathewise/ssg",
3
3
  "description": "Static site generator with TS and JSX support",
4
- "version": "0.9.1",
4
+ "version": "0.10.0",
5
5
  "license": "MPL-2.0",
6
6
  "author": "Andrej Kolčin",
7
7
  "type": "module",
@@ -22,13 +22,13 @@
22
22
  "files": [
23
23
  "dist"
24
24
  ],
25
- "dependencies": {
26
- "tsx": "^4.21.0"
27
- },
28
25
  "devDependencies": {
29
26
  "@biomejs/biome": "^2.2.3",
30
27
  "@types/node": "^24.3.1",
31
28
  "typescript": "^5.9.2",
32
29
  "typescript-language-server": "^4.4.0"
30
+ },
31
+ "dependencies": {
32
+ "rolldown": "^1.0.0-rc.18"
33
33
  }
34
34
  }