@kaathewise/ssg 0.8.5 → 0.9.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.js CHANGED
@@ -4,8 +4,8 @@ import { renderAll } from "./render.js";
4
4
  import { walk } from "./utils.js";
5
5
  export async function build(config) {
6
6
  const pages = [];
7
- for await (const filePath of walk(config.pagesDir)) {
8
- const p = await renderAll(filePath, config.pagesDir);
7
+ for await (const modulePath of walk(config.routesDir)) {
8
+ const p = await renderAll(modulePath, config);
9
9
  pages.push(...p);
10
10
  }
11
11
  await fs.rm(config.outputDir, { recursive: true, force: true });
package/dist/config.d.ts CHANGED
@@ -1,15 +1,21 @@
1
- export type Config = {
2
- pagesDir: string;
3
- sourceDir: string;
1
+ export type ConfigOptions = {
2
+ routesDir?: string;
3
+ assetDir?: string;
4
+ outputDir?: string;
5
+ port?: number;
6
+ loaders?: Loader[];
7
+ };
8
+ export declare class Config {
9
+ routesDir: string;
4
10
  assetDir?: string;
5
11
  outputDir: string;
6
12
  port: number;
13
+ loaders: Loader[];
14
+ constructor(options: ConfigOptions);
15
+ getLoader(modulePath: string): Loader | null;
16
+ }
17
+ export type Loader = {
18
+ matcher: RegExp;
7
19
  };
8
- export declare function defineConfig(options: {
9
- pagesDir: string;
10
- sourceDir: string;
11
- assetDir?: string;
12
- outputDir?: string;
13
- port?: number;
14
- }): Config;
20
+ export declare function defineConfig(options: ConfigOptions): Config;
15
21
  //# sourceMappingURL=config.d.ts.map
@@ -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,GAAG,MAAM,CAaT"}
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"}
package/dist/config.js CHANGED
@@ -1,15 +1,30 @@
1
1
  import * as path from "node:path";
2
2
  const OUTPUT_DIR = "dist/";
3
3
  const DEFAULT_PORT = 3001;
4
- export function defineConfig(options) {
5
- const config = {
6
- pagesDir: path.resolve(options.pagesDir),
7
- sourceDir: path.resolve(options.sourceDir),
8
- outputDir: path.resolve(options.outputDir ?? OUTPUT_DIR),
9
- port: options.port ?? DEFAULT_PORT,
10
- };
11
- if (options.assetDir) {
12
- config.assetDir = path.resolve(options.assetDir);
4
+ export class Config {
5
+ routesDir;
6
+ assetDir;
7
+ outputDir;
8
+ port;
9
+ loaders;
10
+ constructor(options) {
11
+ this.routesDir = path.resolve(options.routesDir ?? "src/routes/");
12
+ this.outputDir = path.resolve(options.outputDir ?? OUTPUT_DIR);
13
+ this.port = options.port ?? DEFAULT_PORT;
14
+ if (options.assetDir) {
15
+ this.assetDir = path.resolve(options.assetDir);
16
+ }
17
+ this.loaders = options.loaders ?? [];
18
+ }
19
+ getLoader(modulePath) {
20
+ for (const loader of this.loaders) {
21
+ if (loader.matcher.test(modulePath)) {
22
+ return loader;
23
+ }
24
+ }
25
+ return null;
13
26
  }
14
- return config;
27
+ }
28
+ export function defineConfig(options) {
29
+ return new Config(options);
15
30
  }
package/dist/render.d.ts CHANGED
@@ -1,10 +1,17 @@
1
+ import type { Config } from "./config.ts";
1
2
  import type { Params } from "./router.ts";
2
3
  export type Page = {
3
4
  path: string;
4
5
  src: string;
5
6
  contentType: string | null;
6
7
  };
7
- export declare function render(modulePath: string, pagesDir: string, params?: Params): Promise<Page>;
8
- export declare function renderAll(modulePath: string, pagesDir: string): Promise<Page[]>;
8
+ export type ArbitraryModule = {
9
+ getStaticParams?(): Params[];
10
+ getContentType?(params: Params): string;
11
+ default?: ((params: Params) => string) | ((params: Params) => Promise<string>);
12
+ };
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[]>;
9
16
  export declare function substituteParams(inputPath: string, params: Params): string;
10
17
  //# sourceMappingURL=render.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,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,CAmBf;AAED,wBAAsB,SAAS,CAC9B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACd,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,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"}
package/dist/render.js CHANGED
@@ -6,34 +6,52 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
6
6
  }
7
7
  return path;
8
8
  };
9
- export async function render(modulePath, pagesDir, params = {}) {
10
- const worker = new Worker(new URL("./render_worker.js", import.meta.url), {
11
- type: "module",
12
- });
13
- return new Promise((resolve, reject) => {
14
- worker.onmessage = (e) => {
15
- worker.terminate();
16
- if (e.data.page) {
17
- resolve(e.data.page);
18
- }
19
- else {
20
- reject(e.data.error);
21
- }
22
- };
23
- worker.postMessage({ modulePath, pagesDir, params });
24
- });
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 });
13
+ return module;
25
14
  }
26
- export async function renderAll(modulePath, pagesDir) {
15
+ export async function render(modulePath, params, config) {
16
+ const module = await load(modulePath);
17
+ let contentType = null;
18
+ if (module.getContentType) {
19
+ contentType = module.getContentType(params);
20
+ }
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
+ }
36
+ let pagePath = path.relative(config.routesDir, modulePath);
37
+ pagePath = substituteParams(pagePath, params);
38
+ pagePath = pagePath.replace(/\.tsx?$/, "");
39
+ if (pagePath.endsWith("index")) {
40
+ pagePath += ".html";
41
+ }
42
+ return { path: pagePath, src, contentType };
43
+ }
44
+ export async function renderAll(modulePath, config) {
27
45
  const module = await import(__rewriteRelativeImportExtension(modulePath));
28
46
  const out = [];
29
47
  if ("getStaticParams" in module) {
30
48
  const paramsList = await module.getStaticParams();
31
49
  for (const params of paramsList) {
32
- out.push(await render(modulePath, pagesDir, params));
50
+ out.push(await render(modulePath, params, config));
33
51
  }
34
52
  }
35
53
  else {
36
- out.push(await render(modulePath, pagesDir));
54
+ out.push(await render(modulePath, {}, config));
37
55
  }
38
56
  return out;
39
57
  }
@@ -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,CAqCzD"}
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"}
package/dist/server.js CHANGED
@@ -8,7 +8,7 @@ import { Router } from "./router.js";
8
8
  const EVENT_PATH = "/__ssg_dev_sse";
9
9
  export async function serve(config) {
10
10
  const clients = new Set();
11
- const router = await Router.new(config.pagesDir);
11
+ const router = await Router.new(config.routesDir);
12
12
  const server = http.createServer(async (request, response) => {
13
13
  const rUrl = new url.URL(request.url ?? "/", "http://localhost");
14
14
  if (rUrl.pathname === EVENT_PATH) {
@@ -17,7 +17,7 @@ export async function serve(config) {
17
17
  }
18
18
  const route = router.match(rUrl.pathname);
19
19
  if (route) {
20
- await serveHtml(response, route, config.pagesDir);
20
+ await serveHtml(response, route, config);
21
21
  return;
22
22
  }
23
23
  if (await fetchStaticFile(response, rUrl, config.assetDir)) {
@@ -29,8 +29,9 @@ export async function serve(config) {
29
29
  });
30
30
  server.listen(config.port);
31
31
  console.log(`Listening on :${config.port}`);
32
- const watcher = watch(config.sourceDir, { recursive: true });
33
- for await (const _ of watcher) {
32
+ const watcher = watch(process.cwd(), { recursive: true });
33
+ for await (const e of watcher) {
34
+ console.log(e);
34
35
  await router.reload();
35
36
  for (const client of clients) {
36
37
  client.write("data: RELOAD\n\n");
@@ -82,9 +83,9 @@ const RELOAD_SCRIPT = `
82
83
  window.addEventListener("beforeunload", () => sse.close())
83
84
  </script>
84
85
  `;
85
- async function serveHtml(response, route, pagesDir) {
86
+ async function serveHtml(response, route, config) {
86
87
  try {
87
- const page = await render(route.filePath, pagesDir, route.params);
88
+ const page = await render(route.filePath, route.params, config);
88
89
  if (page.contentType === "text/html" || !page.contentType) {
89
90
  page.src += RELOAD_SCRIPT;
90
91
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kaathewise/ssg",
3
- "description": "JSX static site generator",
4
- "version": "0.8.5",
3
+ "description": "Static site generator with TS and JSX support",
4
+ "version": "0.9.1",
5
5
  "license": "MPL-2.0",
6
6
  "author": "Andrej Kolčin",
7
7
  "type": "module",
@@ -11,6 +11,7 @@
11
11
  },
12
12
  "scripts": {
13
13
  "check": "biome check && tsc --noEmit",
14
+ "fix": "biome check --fix",
14
15
  "build": "tsc"
15
16
  },
16
17
  "main": "./dist/index.js",
@@ -21,6 +22,9 @@
21
22
  "files": [
22
23
  "dist"
23
24
  ],
25
+ "dependencies": {
26
+ "tsx": "^4.21.0"
27
+ },
24
28
  "devDependencies": {
25
29
  "@biomejs/biome": "^2.2.3",
26
30
  "@types/node": "^24.3.1",
@@ -1,4 +0,0 @@
1
- import { type Page } from "./render.js";
2
- import type { Params } from "./router.ts";
3
- export declare function render(modulePath: string, pagesDir: string, params?: Params): Promise<Page>;
4
- //# sourceMappingURL=render_worker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"render_worker.d.ts","sourceRoot":"","sources":["../src/render_worker.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,EAAoB,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,wBAAsB,MAAM,CAC3B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,MAAW,GACjB,OAAO,CAAC,IAAI,CAAC,CAkCf"}
@@ -1,49 +0,0 @@
1
- var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
- if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
- return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
- return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
- });
6
- }
7
- return path;
8
- };
9
- import * as path from "node:path";
10
- import { substituteParams } from "./render.js";
11
- export async function render(modulePath, pagesDir, params = {}) {
12
- const module = await import(__rewriteRelativeImportExtension(modulePath));
13
- let contentType = null;
14
- if ("getContentType" in module) {
15
- contentType = module.getContentType();
16
- }
17
- const def = module.default;
18
- let src;
19
- switch (typeof def) {
20
- case "string": {
21
- src = def;
22
- break;
23
- }
24
- case "function": {
25
- src = await def(params);
26
- break;
27
- }
28
- default: {
29
- throw "Not implemented";
30
- }
31
- }
32
- let pagePath = path.relative(pagesDir, modulePath);
33
- pagePath = substituteParams(pagePath, params);
34
- pagePath = pagePath.replace(/\.tsx?$/, "");
35
- if (pagePath.endsWith("index")) {
36
- pagePath += ".html";
37
- }
38
- return { path: pagePath, src, contentType };
39
- }
40
- self.onmessage = async (e) => {
41
- const { modulePath, pagesDir, params } = e.data;
42
- try {
43
- const page = await render(modulePath, pagesDir, params);
44
- self.postMessage({ page });
45
- }
46
- catch (err) {
47
- self.postMessage({ error: err });
48
- }
49
- };