defuss-ssg 0.0.1 → 0.0.3

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/README.md CHANGED
@@ -1,14 +1,16 @@
1
1
  <h1 align="center">
2
2
 
3
- <img src="assets/defuss_mascott.png" width="100px" />
3
+ <img src="https://github.com/kyr0/defuss/blob/main/assets/defuss_mascott.png?raw=true" width="100px" />
4
4
 
5
5
  <p align="center">
6
+
6
7
  <code>defuss-ssg</code>
8
+
7
9
  </p>
8
10
 
9
11
  <sup align="center">
10
12
 
11
- Simple Static Site Generator (SSG) for defuss - with support for Markdown, MDX, and Jinja2 templates
13
+ Static Site Generator (SSG) for defuss
12
14
 
13
15
  </sup>
14
16
 
@@ -18,7 +20,7 @@ Simple Static Site Generator (SSG) for defuss - with support for Markdown, MDX,
18
20
  Usage
19
21
  </h3>
20
22
 
21
- Simply generate a static site from a content directory to an output directory with full `defuss`-MDX (GFM + Frontmatter) support:
23
+ Simply generate a static site from a content directory to an output directory with full defuss-MDX (GFM + Frontmatter) support:
22
24
 
23
25
  ```bash
24
26
  npx defuss-ssg build ./folder
@@ -57,9 +59,17 @@ Changes trigger automatic rebuilds, with the last change always taking priority
57
59
  Advanced users may want to use the library programmatically:
58
60
 
59
61
  ```typescript
60
- import { build, serve } from "defuss-ssg";
62
+ import { setup, build, serve } from "defuss-ssg";
61
63
 
62
64
  (async () => {
65
+
66
+ // Setup project initially
67
+ const setupStatus = await setup("./my-site");
68
+ if (setupStatus.code !== "OK") {
69
+ console.error("Setup failed:", setupStatus.message);
70
+ process.exit(1);
71
+ }
72
+
63
73
  // One-time build
64
74
  await build({
65
75
  projectDir: "./my-site",
package/dist/cli.cjs CHANGED
@@ -1,15 +1,20 @@
1
1
  'use strict';
2
2
 
3
- var serve = require('./serve-BaOtT5p7.cjs');
3
+ var serve = require('./serve-KTJqW3m0.cjs');
4
4
  var node_path = require('node:path');
5
+ var node_fs = require('node:fs');
6
+ var node_child_process = require('node:child_process');
5
7
  require('chokidar');
6
8
  require('express');
7
9
  require('serve-static');
8
- require('node:fs');
9
10
  require('esbuild');
10
- require('remark-frontmatter');
11
11
  require('rehype-katex');
12
+ require('rehype-stringify');
13
+ require('remark-frontmatter');
12
14
  require('remark-math');
15
+ require('remark-gfm');
16
+ require('remark-parse');
17
+ require('remark-rehype');
13
18
  require('remark-mdx-frontmatter');
14
19
  require('./tailwind-C4AuHybm.cjs');
15
20
  require('@mdx-js/esbuild');
@@ -18,6 +23,47 @@ require('defuss/server');
18
23
  require('node:fs/promises');
19
24
  require('node:url');
20
25
 
26
+ const setup = async (projectDir) => {
27
+ const projectDirStatus = serve.validateProjectDir(projectDir);
28
+ if (projectDirStatus.code !== "OK") return projectDirStatus;
29
+ const packageJsonPath = node_path.join(projectDir, "package.json");
30
+ if (!node_fs.existsSync(packageJsonPath)) {
31
+ return {
32
+ code: "MISSING_PACKAGE_JSON",
33
+ message: `package.json not found in ${projectDir}`
34
+ };
35
+ }
36
+ let packageJson;
37
+ try {
38
+ packageJson = JSON.parse(node_fs.readFileSync(packageJsonPath, "utf-8"));
39
+ } catch (error) {
40
+ return {
41
+ code: "INVALID_JSON",
42
+ message: `Error reading package.json in ${projectDir}: ${error.message}`
43
+ };
44
+ }
45
+ const packageManager = packageJson.packageManager || "npm";
46
+ const pm = packageManager.split("@")[0];
47
+ const validPMs = ["npm", "yarn", "pnpm", "bun"];
48
+ if (!validPMs.includes(pm)) {
49
+ return {
50
+ code: "UNSUPPORTED_PM",
51
+ message: `Unsupported package manager: ${pm}`
52
+ };
53
+ }
54
+ console.log(`Setting up project in ${projectDir} using ${pm}...`);
55
+ try {
56
+ node_child_process.execSync(`${pm} install`, { cwd: projectDir, stdio: "inherit" });
57
+ console.log("Dependencies installed successfully.");
58
+ } catch (error) {
59
+ return {
60
+ code: "INSTALL_FAILED",
61
+ message: `Failed to install dependencies: ${error.message}`
62
+ };
63
+ }
64
+ return { code: "OK", message: "Setup completed successfully" };
65
+ };
66
+
21
67
  (async () => {
22
68
  const args = process.argv.slice(2);
23
69
  const command = args[0];
@@ -28,6 +74,7 @@ require('node:url');
28
74
  process.exit(1);
29
75
  }
30
76
  const projectDir = node_path.resolve(folder);
77
+ await setup(projectDir);
31
78
  if (command === "build") {
32
79
  console.log(`Building ${folder}...`);
33
80
  await serve.build({
package/dist/cli.mjs CHANGED
@@ -1,14 +1,19 @@
1
1
  #!/usr/bin/env node
2
- import { d as build, s as serve } from './serve-COHw7ASj.mjs';
3
- import { resolve } from 'node:path';
2
+ import { v as validateProjectDir, d as build, s as serve } from './serve-CzCDilBA.mjs';
3
+ import { join, resolve } from 'node:path';
4
+ import { existsSync, readFileSync } from 'node:fs';
5
+ import { execSync } from 'node:child_process';
4
6
  import 'chokidar';
5
7
  import 'express';
6
8
  import 'serve-static';
7
- import 'node:fs';
8
9
  import 'esbuild';
9
- import 'remark-frontmatter';
10
10
  import 'rehype-katex';
11
+ import 'rehype-stringify';
12
+ import 'remark-frontmatter';
11
13
  import 'remark-math';
14
+ import 'remark-gfm';
15
+ import 'remark-parse';
16
+ import 'remark-rehype';
12
17
  import 'remark-mdx-frontmatter';
13
18
  import './tailwind-DV23JSh-.mjs';
14
19
  import '@mdx-js/esbuild';
@@ -17,6 +22,47 @@ import 'defuss/server';
17
22
  import 'node:fs/promises';
18
23
  import 'node:url';
19
24
 
25
+ const setup = async (projectDir) => {
26
+ const projectDirStatus = validateProjectDir(projectDir);
27
+ if (projectDirStatus.code !== "OK") return projectDirStatus;
28
+ const packageJsonPath = join(projectDir, "package.json");
29
+ if (!existsSync(packageJsonPath)) {
30
+ return {
31
+ code: "MISSING_PACKAGE_JSON",
32
+ message: `package.json not found in ${projectDir}`
33
+ };
34
+ }
35
+ let packageJson;
36
+ try {
37
+ packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
38
+ } catch (error) {
39
+ return {
40
+ code: "INVALID_JSON",
41
+ message: `Error reading package.json in ${projectDir}: ${error.message}`
42
+ };
43
+ }
44
+ const packageManager = packageJson.packageManager || "npm";
45
+ const pm = packageManager.split("@")[0];
46
+ const validPMs = ["npm", "yarn", "pnpm", "bun"];
47
+ if (!validPMs.includes(pm)) {
48
+ return {
49
+ code: "UNSUPPORTED_PM",
50
+ message: `Unsupported package manager: ${pm}`
51
+ };
52
+ }
53
+ console.log(`Setting up project in ${projectDir} using ${pm}...`);
54
+ try {
55
+ execSync(`${pm} install`, { cwd: projectDir, stdio: "inherit" });
56
+ console.log("Dependencies installed successfully.");
57
+ } catch (error) {
58
+ return {
59
+ code: "INSTALL_FAILED",
60
+ message: `Failed to install dependencies: ${error.message}`
61
+ };
62
+ }
63
+ return { code: "OK", message: "Setup completed successfully" };
64
+ };
65
+
20
66
  (async () => {
21
67
  const args = process.argv.slice(2);
22
68
  const command = args[0];
@@ -27,6 +73,7 @@ import 'node:url';
27
73
  process.exit(1);
28
74
  }
29
75
  const projectDir = resolve(folder);
76
+ await setup(projectDir);
30
77
  if (command === "build") {
31
78
  console.log(`Building ${folder}...`);
32
79
  await build({
package/dist/index.cjs CHANGED
@@ -1,15 +1,19 @@
1
1
  'use strict';
2
2
 
3
- var serve = require('./serve-BaOtT5p7.cjs');
3
+ var serve = require('./serve-KTJqW3m0.cjs');
4
4
  require('chokidar');
5
5
  require('express');
6
6
  require('serve-static');
7
7
  require('node:path');
8
8
  require('node:fs');
9
9
  require('esbuild');
10
- require('remark-frontmatter');
11
10
  require('rehype-katex');
11
+ require('rehype-stringify');
12
+ require('remark-frontmatter');
12
13
  require('remark-math');
14
+ require('remark-gfm');
15
+ require('remark-parse');
16
+ require('remark-rehype');
13
17
  require('remark-mdx-frontmatter');
14
18
  require('./tailwind-C4AuHybm.cjs');
15
19
  require('@mdx-js/esbuild');
package/dist/index.d.cts CHANGED
@@ -1,11 +1,17 @@
1
- import { R as RemarkPlugins, a as RehypePlugins, S as SsgConfig, B as BuildOptions } from './types-D1n7GtYH.js';
2
- export { e as BuildMode, f as PluginFn, c as PluginFnPageDom, P as PluginFnPageHtml, b as PluginFnPageVdom, d as PluginFnPrePost, g as SsgPlugin } from './types-D1n7GtYH.js';
1
+ import { R as RemarkPlugins, a as RehypePlugins, S as SsgConfig, B as BuildOptions, b as Status } from './types-BWD2Kt6_.js';
2
+ export { g as BuildMode, h as PluginFn, e as PluginFnPageDom, P as PluginFnPageHtml, d as PluginFnPageVdom, f as PluginFnPrePost, i as SsgPlugin, c as StatusCode } from './types-BWD2Kt6_.js';
3
3
  import '@mdx-js/esbuild';
4
4
  import 'defuss/server';
5
5
 
6
6
  declare const remarkPlugins: RemarkPlugins;
7
7
  declare const rehypePlugins: RehypePlugins;
8
8
 
9
+ /**
10
+ * Reads the SSG configuration from the project directory.
11
+ * @param projectDir The path to the project directory.
12
+ * @param debug Whether to enable debug logging.
13
+ * @returns The SSG configuration.
14
+ */
9
15
  declare const readConfig: (projectDir: string, debug: boolean) => Promise<SsgConfig>;
10
16
  declare const configDefaults: SsgConfig;
11
17
 
@@ -13,13 +19,13 @@ declare const configDefaults: SsgConfig;
13
19
  * A single, complete build process for a static site project.
14
20
  * @param projectDir The root directory of the project to build
15
21
  */
16
- declare const build: ({ projectDir, debug, mode, }: BuildOptions) => Promise<void>;
22
+ declare const build: ({ projectDir, debug, mode, }: BuildOptions) => Promise<Status>;
17
23
 
18
24
  /**
19
25
  * A simple static file server to serve the generated static site from the output folder.
20
26
  * Also watches the input, components and assets folders for changes and rebuilds the site on-the-fly.
21
27
  * @param projectDir The root directory of the project to build
22
28
  */
23
- declare const serve: ({ projectDir, debug }: BuildOptions) => Promise<void>;
29
+ declare const serve: ({ projectDir, debug, }: BuildOptions) => Promise<Status>;
24
30
 
25
- export { BuildOptions, RehypePlugins, RemarkPlugins, SsgConfig, build, configDefaults, readConfig, rehypePlugins, remarkPlugins, serve };
31
+ export { BuildOptions, RehypePlugins, RemarkPlugins, SsgConfig, Status, build, configDefaults, readConfig, rehypePlugins, remarkPlugins, serve };
package/dist/index.d.mts CHANGED
@@ -1,11 +1,17 @@
1
- import { R as RemarkPlugins, a as RehypePlugins, S as SsgConfig, B as BuildOptions } from './types-D1n7GtYH.js';
2
- export { e as BuildMode, f as PluginFn, c as PluginFnPageDom, P as PluginFnPageHtml, b as PluginFnPageVdom, d as PluginFnPrePost, g as SsgPlugin } from './types-D1n7GtYH.js';
1
+ import { R as RemarkPlugins, a as RehypePlugins, S as SsgConfig, B as BuildOptions, b as Status } from './types-BWD2Kt6_.js';
2
+ export { g as BuildMode, h as PluginFn, e as PluginFnPageDom, P as PluginFnPageHtml, d as PluginFnPageVdom, f as PluginFnPrePost, i as SsgPlugin, c as StatusCode } from './types-BWD2Kt6_.js';
3
3
  import '@mdx-js/esbuild';
4
4
  import 'defuss/server';
5
5
 
6
6
  declare const remarkPlugins: RemarkPlugins;
7
7
  declare const rehypePlugins: RehypePlugins;
8
8
 
9
+ /**
10
+ * Reads the SSG configuration from the project directory.
11
+ * @param projectDir The path to the project directory.
12
+ * @param debug Whether to enable debug logging.
13
+ * @returns The SSG configuration.
14
+ */
9
15
  declare const readConfig: (projectDir: string, debug: boolean) => Promise<SsgConfig>;
10
16
  declare const configDefaults: SsgConfig;
11
17
 
@@ -13,13 +19,13 @@ declare const configDefaults: SsgConfig;
13
19
  * A single, complete build process for a static site project.
14
20
  * @param projectDir The root directory of the project to build
15
21
  */
16
- declare const build: ({ projectDir, debug, mode, }: BuildOptions) => Promise<void>;
22
+ declare const build: ({ projectDir, debug, mode, }: BuildOptions) => Promise<Status>;
17
23
 
18
24
  /**
19
25
  * A simple static file server to serve the generated static site from the output folder.
20
26
  * Also watches the input, components and assets folders for changes and rebuilds the site on-the-fly.
21
27
  * @param projectDir The root directory of the project to build
22
28
  */
23
- declare const serve: ({ projectDir, debug }: BuildOptions) => Promise<void>;
29
+ declare const serve: ({ projectDir, debug, }: BuildOptions) => Promise<Status>;
24
30
 
25
- export { BuildOptions, RehypePlugins, RemarkPlugins, SsgConfig, build, configDefaults, readConfig, rehypePlugins, remarkPlugins, serve };
31
+ export { BuildOptions, RehypePlugins, RemarkPlugins, SsgConfig, Status, build, configDefaults, readConfig, rehypePlugins, remarkPlugins, serve };
package/dist/index.mjs CHANGED
@@ -1,13 +1,17 @@
1
- export { d as build, c as configDefaults, b as readConfig, a as rehypePlugins, r as remarkPlugins, s as serve } from './serve-COHw7ASj.mjs';
1
+ export { d as build, c as configDefaults, b as readConfig, a as rehypePlugins, r as remarkPlugins, s as serve } from './serve-CzCDilBA.mjs';
2
2
  import 'chokidar';
3
3
  import 'express';
4
4
  import 'serve-static';
5
5
  import 'node:path';
6
6
  import 'node:fs';
7
7
  import 'esbuild';
8
- import 'remark-frontmatter';
9
8
  import 'rehype-katex';
9
+ import 'rehype-stringify';
10
+ import 'remark-frontmatter';
10
11
  import 'remark-math';
12
+ import 'remark-gfm';
13
+ import 'remark-parse';
14
+ import 'remark-rehype';
11
15
  import 'remark-mdx-frontmatter';
12
16
  import './tailwind-DV23JSh-.mjs';
13
17
  import '@mdx-js/esbuild';
@@ -1,4 +1,4 @@
1
- import { g as SsgPlugin, d as PluginFnPrePost } from '../types-D1n7GtYH.js';
1
+ import { i as SsgPlugin, f as PluginFnPrePost } from '../types-BWD2Kt6_.js';
2
2
  import '@mdx-js/esbuild';
3
3
  import 'defuss/server';
4
4
 
@@ -1,4 +1,4 @@
1
- import { g as SsgPlugin, d as PluginFnPrePost } from '../types-D1n7GtYH.js';
1
+ import { i as SsgPlugin, f as PluginFnPrePost } from '../types-BWD2Kt6_.js';
2
2
  import '@mdx-js/esbuild';
3
3
  import 'defuss/server';
4
4
 
@@ -2,11 +2,15 @@ import chokidar from 'chokidar';
2
2
  import express from 'express';
3
3
  import serveStatic from 'serve-static';
4
4
  import { join, resolve, dirname, sep } from 'node:path';
5
- import { existsSync, rmdirSync, mkdirSync } from 'node:fs';
5
+ import { existsSync, statSync, rmdirSync, mkdirSync } from 'node:fs';
6
6
  import esbuild from 'esbuild';
7
- import remarkFrontmatter from 'remark-frontmatter';
8
7
  import rehypeKatex from 'rehype-katex';
8
+ import rehypeStringify from 'rehype-stringify';
9
+ import remarkFrontmatter from 'remark-frontmatter';
9
10
  import remarkMath from 'remark-math';
11
+ import remarkGfm from 'remark-gfm';
12
+ import remarkParse from 'remark-parse';
13
+ import remarkRehype from 'remark-rehype';
10
14
  import remarkMdxFrontmatter from 'remark-mdx-frontmatter';
11
15
  import { t as tailwindPlugin } from './tailwind-DV23JSh-.mjs';
12
16
  import mdx from '@mdx-js/esbuild';
@@ -16,16 +20,21 @@ import { cp, readFile, writeFile } from 'node:fs/promises';
16
20
  import { fileURLToPath } from 'node:url';
17
21
 
18
22
  const remarkPlugins = [
23
+ remarkParse,
19
24
  // Parse both YAML and TOML (or omit options to default to YAML)
20
25
  [remarkFrontmatter, ["yaml", "toml"]],
21
26
  // Export each key as an ESM binding: export const title = "…"
22
27
  [remarkMdxFrontmatter, { name: "meta" }],
28
+ // GitHub Flavored Markdown (tables, task lists, strikethrough, etc.)
29
+ remarkGfm,
30
+ remarkRehype,
23
31
  // Convert $…$ and $$…$$ into math nodes for KaTeX
24
32
  remarkMath
25
33
  ];
26
34
  const rehypePlugins = [
27
35
  //rehypeMdxTitle,
28
- rehypeKatex
36
+ rehypeKatex,
37
+ rehypeStringify
29
38
  ];
30
39
 
31
40
  const readConfig = async (projectDir, debug) => {
@@ -69,6 +78,23 @@ const configDefaults = {
69
78
  rehypePlugins
70
79
  };
71
80
 
81
+ const validateProjectDir = (projectDir) => {
82
+ try {
83
+ if (!statSync(projectDir).isDirectory()) {
84
+ return {
85
+ code: "MISSING_PROJECT_DIR",
86
+ message: `Project directory is not a directory: ${projectDir}`
87
+ };
88
+ }
89
+ } catch (error) {
90
+ return {
91
+ code: "INVALID_PROJECT_DIR",
92
+ message: `Error accessing project directory: ${error.message}`
93
+ };
94
+ }
95
+ return { code: "OK", message: "Project directory is valid." };
96
+ };
97
+
72
98
  const __filename = fileURLToPath(import.meta.url);
73
99
  const __dirname = dirname(__filename);
74
100
  const build = async ({
@@ -76,6 +102,8 @@ const build = async ({
76
102
  debug = false,
77
103
  mode = "build"
78
104
  }) => {
105
+ const projectDirStatus = validateProjectDir(projectDir);
106
+ if (projectDirStatus.code !== "OK") return projectDirStatus;
79
107
  const startTime = performance.now();
80
108
  const config = await readConfig(projectDir, debug);
81
109
  if (debug) {
@@ -147,20 +175,16 @@ const build = async ({
147
175
  }
148
176
  });
149
177
  await cp(
150
- // because of this the packaging of defuss-ssg must be done with "files" including the "components" folder
151
178
  // in a built situation, __dirname is the dist folder of defuss-ssg
152
179
  resolve(join(__dirname, "components", "index.mjs")),
153
- // dist folder
154
180
  join(tmpComponentsDir, "hydrate.tsx")
155
- // a valid JS is always a valid TS file
181
+ // any valid JS is always a valid TS file
156
182
  );
157
183
  await cp(
158
- // because of this the packaging of defuss-ssg must be done with "files" including the "runtime" file
159
184
  // in a built situation, __dirname is the dist folder of defuss-ssg
160
185
  resolve(join(__dirname, "runtime.mjs")),
161
- // dist folder
162
186
  join(tmpComponentsDir, "runtime.ts")
163
- // a valid JS is always a valid TS file
187
+ // any valid JS is always a valid TS file
164
188
  );
165
189
  await esbuild.build({
166
190
  entryPoints: [join(tmpPagesDir, "**/*.mdx")],
@@ -297,9 +321,13 @@ const build = async ({
297
321
  const endTime = performance.now();
298
322
  const totalTime = (endTime - startTime) / 1e3;
299
323
  console.log(`Build completed in ${totalTime.toFixed(2)} seconds.`);
324
+ return { code: "OK", message: "Build completed successfully" };
300
325
  };
301
326
 
302
- const serve = async ({ projectDir, debug = false }) => {
327
+ const serve = async ({
328
+ projectDir,
329
+ debug = false
330
+ }) => {
303
331
  const config = await readConfig(projectDir, debug);
304
332
  const outputDir = join(projectDir, config.output);
305
333
  const pagesDir = join(projectDir, config.pages);
@@ -325,6 +353,8 @@ const serve = async ({ projectDir, debug = false }) => {
325
353
  isBuilding = true;
326
354
  try {
327
355
  await build({ projectDir, debug, mode: "serve" });
356
+ } catch (error) {
357
+ console.error("Build failed. Waiting for code change to fix that...");
328
358
  } finally {
329
359
  isBuilding = false;
330
360
  if (pendingBuild) {
@@ -361,6 +391,7 @@ const serve = async ({ projectDir, debug = false }) => {
361
391
  }
362
392
  await triggerBuild();
363
393
  });
394
+ return { code: "OK", message: "Server is running" };
364
395
  };
365
396
 
366
- export { rehypePlugins as a, readConfig as b, configDefaults as c, build as d, remarkPlugins as r, serve as s };
397
+ export { rehypePlugins as a, readConfig as b, configDefaults as c, build as d, remarkPlugins as r, serve as s, validateProjectDir as v };
@@ -6,9 +6,13 @@ var serveStatic = require('serve-static');
6
6
  var node_path = require('node:path');
7
7
  var node_fs = require('node:fs');
8
8
  var esbuild = require('esbuild');
9
- var remarkFrontmatter = require('remark-frontmatter');
10
9
  var rehypeKatex = require('rehype-katex');
10
+ var rehypeStringify = require('rehype-stringify');
11
+ var remarkFrontmatter = require('remark-frontmatter');
11
12
  var remarkMath = require('remark-math');
13
+ var remarkGfm = require('remark-gfm');
14
+ var remarkParse = require('remark-parse');
15
+ var remarkRehype = require('remark-rehype');
12
16
  var remarkMdxFrontmatter = require('remark-mdx-frontmatter');
13
17
  var tailwind = require('./tailwind-C4AuHybm.cjs');
14
18
  var mdx = require('@mdx-js/esbuild');
@@ -19,16 +23,21 @@ var node_url = require('node:url');
19
23
 
20
24
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
21
25
  const remarkPlugins = [
26
+ remarkParse,
22
27
  // Parse both YAML and TOML (or omit options to default to YAML)
23
28
  [remarkFrontmatter, ["yaml", "toml"]],
24
29
  // Export each key as an ESM binding: export const title = "…"
25
30
  [remarkMdxFrontmatter, { name: "meta" }],
31
+ // GitHub Flavored Markdown (tables, task lists, strikethrough, etc.)
32
+ remarkGfm,
33
+ remarkRehype,
26
34
  // Convert $…$ and $$…$$ into math nodes for KaTeX
27
35
  remarkMath
28
36
  ];
29
37
  const rehypePlugins = [
30
38
  //rehypeMdxTitle,
31
- rehypeKatex
39
+ rehypeKatex,
40
+ rehypeStringify
32
41
  ];
33
42
 
34
43
  const readConfig = async (projectDir, debug) => {
@@ -72,13 +81,32 @@ const configDefaults = {
72
81
  rehypePlugins
73
82
  };
74
83
 
75
- const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('serve-BaOtT5p7.cjs', document.baseURI).href)));
84
+ const validateProjectDir = (projectDir) => {
85
+ try {
86
+ if (!node_fs.statSync(projectDir).isDirectory()) {
87
+ return {
88
+ code: "MISSING_PROJECT_DIR",
89
+ message: `Project directory is not a directory: ${projectDir}`
90
+ };
91
+ }
92
+ } catch (error) {
93
+ return {
94
+ code: "INVALID_PROJECT_DIR",
95
+ message: `Error accessing project directory: ${error.message}`
96
+ };
97
+ }
98
+ return { code: "OK", message: "Project directory is valid." };
99
+ };
100
+
101
+ const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('serve-KTJqW3m0.cjs', document.baseURI).href)));
76
102
  const __dirname$1 = node_path.dirname(__filename$1);
77
103
  const build = async ({
78
104
  projectDir,
79
105
  debug = false,
80
106
  mode = "build"
81
107
  }) => {
108
+ const projectDirStatus = validateProjectDir(projectDir);
109
+ if (projectDirStatus.code !== "OK") return projectDirStatus;
82
110
  const startTime = performance.now();
83
111
  const config = await readConfig(projectDir, debug);
84
112
  if (debug) {
@@ -150,20 +178,16 @@ const build = async ({
150
178
  }
151
179
  });
152
180
  await promises.cp(
153
- // because of this the packaging of defuss-ssg must be done with "files" including the "components" folder
154
181
  // in a built situation, __dirname is the dist folder of defuss-ssg
155
182
  node_path.resolve(node_path.join(__dirname$1, "components", "index.mjs")),
156
- // dist folder
157
183
  node_path.join(tmpComponentsDir, "hydrate.tsx")
158
- // a valid JS is always a valid TS file
184
+ // any valid JS is always a valid TS file
159
185
  );
160
186
  await promises.cp(
161
- // because of this the packaging of defuss-ssg must be done with "files" including the "runtime" file
162
187
  // in a built situation, __dirname is the dist folder of defuss-ssg
163
188
  node_path.resolve(node_path.join(__dirname$1, "runtime.mjs")),
164
- // dist folder
165
189
  node_path.join(tmpComponentsDir, "runtime.ts")
166
- // a valid JS is always a valid TS file
190
+ // any valid JS is always a valid TS file
167
191
  );
168
192
  await esbuild.build({
169
193
  entryPoints: [node_path.join(tmpPagesDir, "**/*.mdx")],
@@ -300,9 +324,13 @@ const build = async ({
300
324
  const endTime = performance.now();
301
325
  const totalTime = (endTime - startTime) / 1e3;
302
326
  console.log(`Build completed in ${totalTime.toFixed(2)} seconds.`);
327
+ return { code: "OK", message: "Build completed successfully" };
303
328
  };
304
329
 
305
- const serve = async ({ projectDir, debug = false }) => {
330
+ const serve = async ({
331
+ projectDir,
332
+ debug = false
333
+ }) => {
306
334
  const config = await readConfig(projectDir, debug);
307
335
  const outputDir = node_path.join(projectDir, config.output);
308
336
  const pagesDir = node_path.join(projectDir, config.pages);
@@ -328,6 +356,8 @@ const serve = async ({ projectDir, debug = false }) => {
328
356
  isBuilding = true;
329
357
  try {
330
358
  await build({ projectDir, debug, mode: "serve" });
359
+ } catch (error) {
360
+ console.error("Build failed. Waiting for code change to fix that...");
331
361
  } finally {
332
362
  isBuilding = false;
333
363
  if (pendingBuild) {
@@ -364,6 +394,7 @@ const serve = async ({ projectDir, debug = false }) => {
364
394
  }
365
395
  await triggerBuild();
366
396
  });
397
+ return { code: "OK", message: "Server is running" };
367
398
  };
368
399
 
369
400
  exports.build = build;
@@ -372,3 +403,4 @@ exports.readConfig = readConfig;
372
403
  exports.rehypePlugins = rehypePlugins;
373
404
  exports.remarkPlugins = remarkPlugins;
374
405
  exports.serve = serve;
406
+ exports.validateProjectDir = validateProjectDir;
@@ -3,6 +3,11 @@ import { VNode } from 'defuss/server';
3
3
 
4
4
  type RemarkPlugins = Options["remarkPlugins"];
5
5
  type RehypePlugins = Options["rehypePlugins"];
6
+ type StatusCode = "OK" | "MISSING_PROJECT_DIR" | "MISSING_PACKAGE_JSON" | "INVALID_JSON" | "UNSUPPORTED_PM" | "INSTALL_FAILED" | "INVALID_CONFIG" | "INVALID_PROJECT_DIR";
7
+ type Status = {
8
+ code: StatusCode;
9
+ message: string;
10
+ };
6
11
  type PluginFnPageHtml = (html: string, relativeOutputHtmlFilePath: string, projectDir: string, config: SsgConfig) => Promise<string> | string;
7
12
  type PluginFnPageVdom = (vdom: VNode, relativeOutputHtmlFilePath: string, projectDir: string, config: SsgConfig) => Promise<VNode> | VNode;
8
13
  type PluginFnPageDom = (dom: HTMLElement, relativeOutputHtmlFilePath: string, projectDir: string, config: SsgConfig) => Promise<HTMLElement> | HTMLElement;
@@ -98,4 +103,4 @@ interface SsgConfig {
98
103
  rehypePlugins: Options["rehypePlugins"];
99
104
  }
100
105
 
101
- export type { BuildOptions as B, PluginFnPageHtml as P, RemarkPlugins as R, SsgConfig as S, RehypePlugins as a, PluginFnPageVdom as b, PluginFnPageDom as c, PluginFnPrePost as d, BuildMode as e, PluginFn as f, SsgPlugin as g };
106
+ export type { BuildOptions as B, PluginFnPageHtml as P, RemarkPlugins as R, SsgConfig as S, RehypePlugins as a, Status as b, StatusCode as c, PluginFnPageVdom as d, PluginFnPageDom as e, PluginFnPrePost as f, BuildMode as g, PluginFn as h, SsgPlugin as i };
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "defuss-ssg",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
- "bin": "./dist/cli.mjs",
8
+ "bin": {
9
+ "defuss-ssg": "dist/cli.mjs"
10
+ },
9
11
  "license": "MIT",
10
12
  "description": "A simple static site generator (SSG) built with defuss.",
11
13
  "keywords": ["ssg", "static", "site", "generator", "defuss"],
@@ -81,7 +83,11 @@
81
83
  "esbuild": "^0.25.9",
82
84
  "rehype-mdx-title": "^3.2.0",
83
85
  "rehype-katex": "^7.0.1",
86
+ "rehype-stringify": "^10.0.1",
87
+ "remark-rehype": "^11.1.2",
84
88
  "remark-math": "^6.0.0",
89
+ "remark-gfm": "^4.0.1",
90
+ "remark-parse": "^11.0.0",
85
91
  "remark-frontmatter": "^5.0.0",
86
92
  "remark-mdx-frontmatter": "^5.2.0",
87
93
  "fast-glob": "^3.3.3",