docgen-tool 6.4.1 → 6.4.2
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/cli/cli.js +113 -70
- package/package.json +8 -9
package/dist/cli/cli.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
2
|
import { program } from "commander";
|
|
4
3
|
import path, { join, resolve } from "node:path";
|
|
5
4
|
import { build, createServer } from "vite";
|
|
6
5
|
import react from "@vitejs/plugin-react";
|
|
7
|
-
import { nodePolyfills } from "vite-plugin-node-polyfills";
|
|
8
6
|
import dotenv from "dotenv";
|
|
9
7
|
import pico from "picocolors";
|
|
10
8
|
import path$1 from "path";
|
|
@@ -14,7 +12,14 @@ import schemaValidator from "z-schema";
|
|
|
14
12
|
import fs$1, { accessSync, constants } from "node:fs";
|
|
15
13
|
import StyleDictionary from "style-dictionary";
|
|
16
14
|
const deriveParameters = ({ rawParameters, setVersion, setReleaseDate }) => {
|
|
17
|
-
const version$1 = setVersion || rawParameters.version
|
|
15
|
+
const version$1 = setVersion || rawParameters.version;
|
|
16
|
+
const releaseDate = setReleaseDate || rawParameters.date;
|
|
17
|
+
const currentDate = /* @__PURE__ */ new Date();
|
|
18
|
+
const date = currentDate.toLocaleDateString("en-GB");
|
|
19
|
+
const time = currentDate.toLocaleTimeString("en-US", { hour12: false });
|
|
20
|
+
const year = currentDate.getFullYear().toString();
|
|
21
|
+
const attribution = `Created by DocGen ${version$1} on ${date} at ${time}.`;
|
|
22
|
+
const webFooter = `Version ${version$1} released on ${releaseDate}`;
|
|
18
23
|
return {
|
|
19
24
|
...rawParameters,
|
|
20
25
|
attribution,
|
|
@@ -23,22 +28,27 @@ const deriveParameters = ({ rawParameters, setVersion, setReleaseDate }) => {
|
|
|
23
28
|
version: version$1,
|
|
24
29
|
releaseDate
|
|
25
30
|
};
|
|
26
|
-
}
|
|
31
|
+
};
|
|
32
|
+
const readFile = async (filePath) => {
|
|
27
33
|
const normalized = path$1.normalize(filePath);
|
|
28
34
|
try {
|
|
29
|
-
|
|
30
|
-
return content?.replace(/^\uFEFF/, "");
|
|
35
|
+
return (await promises.readFile(normalized, { encoding: "utf8" }))?.replace(/^\uFEFF/, "");
|
|
31
36
|
} catch (error) {
|
|
32
|
-
|
|
37
|
+
console.log(pico.red(`Error reading file: ${normalized}`));
|
|
38
|
+
if (error instanceof Error) console.log(pico.dim(error.message));
|
|
33
39
|
}
|
|
34
|
-
}
|
|
35
|
-
|
|
40
|
+
};
|
|
41
|
+
const copyDirectory = async (source, destination, verbose) => {
|
|
42
|
+
const normalizedSource = path$1.normalize(source);
|
|
43
|
+
const normalizedDestination = path$1.normalize(destination);
|
|
36
44
|
try {
|
|
37
45
|
await fs.copySync(normalizedSource, normalizedDestination);
|
|
38
46
|
} catch (error) {
|
|
39
|
-
|
|
47
|
+
console.log(pico.red("Error copying directory: " + normalizedSource + " to " + normalizedDestination));
|
|
48
|
+
if (verbose === true) console.log(pico.red(error));
|
|
40
49
|
}
|
|
41
|
-
}
|
|
50
|
+
};
|
|
51
|
+
var schemas = {
|
|
42
52
|
parameters: {
|
|
43
53
|
title: "DocGen Parameters Schema",
|
|
44
54
|
type: "object",
|
|
@@ -166,13 +176,18 @@ const deriveParameters = ({ rawParameters, setVersion, setReleaseDate }) => {
|
|
|
166
176
|
}
|
|
167
177
|
}] }
|
|
168
178
|
}
|
|
169
|
-
}
|
|
170
|
-
|
|
179
|
+
};
|
|
180
|
+
const validateJSON = ({ key, data, verbose }) => {
|
|
181
|
+
let schema = schemas[key];
|
|
182
|
+
let validator = new schemaValidator({});
|
|
183
|
+
let valid = validator.validate(data, schema);
|
|
171
184
|
if (!valid) {
|
|
172
|
-
|
|
185
|
+
console.log(pico.red(`Error parsing required file: ${key}.json (failed schema validation)`));
|
|
186
|
+
if (verbose === true) console.log(pico.red(validator.getLastError().message));
|
|
173
187
|
}
|
|
174
188
|
return valid;
|
|
175
|
-
}
|
|
189
|
+
};
|
|
190
|
+
const loadInputs = async ({ inputPath, verbose }) => {
|
|
176
191
|
const inputConfig = {
|
|
177
192
|
parameters: null,
|
|
178
193
|
contents: []
|
|
@@ -191,24 +206,27 @@ const deriveParameters = ({ rawParameters, setVersion, setReleaseDate }) => {
|
|
|
191
206
|
verbose
|
|
192
207
|
})) inputConfig[key] = file;
|
|
193
208
|
} catch (error) {
|
|
194
|
-
|
|
209
|
+
console.log(pico.red("Error parsing required file: " + key + ".json (invalid JSON)"));
|
|
210
|
+
if (verbose === true) console.log(pico.red(error));
|
|
195
211
|
}
|
|
196
|
-
|
|
212
|
+
inputConfig.contents.push({
|
|
197
213
|
heading: "Extra",
|
|
198
214
|
column: 5,
|
|
199
215
|
pages: [{
|
|
200
216
|
title: "Release notes",
|
|
201
217
|
source: "release-notes.md"
|
|
202
218
|
}]
|
|
203
|
-
};
|
|
204
|
-
return
|
|
219
|
+
});
|
|
220
|
+
return {
|
|
205
221
|
rawParameters: inputConfig.parameters,
|
|
206
222
|
contents: inputConfig.contents
|
|
207
223
|
};
|
|
208
224
|
} catch (error) {
|
|
209
|
-
|
|
225
|
+
console.log(pico.red("Error loading required JSON metadata files"));
|
|
226
|
+
if (verbose === true) console.log(pico.red(error));
|
|
210
227
|
}
|
|
211
|
-
}
|
|
228
|
+
};
|
|
229
|
+
const sortPages = ({ contents }) => {
|
|
212
230
|
return contents.reduce((acc, section) => {
|
|
213
231
|
const { column } = section;
|
|
214
232
|
return {
|
|
@@ -222,30 +240,42 @@ const deriveParameters = ({ rawParameters, setVersion, setReleaseDate }) => {
|
|
|
222
240
|
4: [],
|
|
223
241
|
5: []
|
|
224
242
|
});
|
|
225
|
-
}
|
|
243
|
+
};
|
|
244
|
+
const findPackageRoot = (start = import.meta.dirname) => {
|
|
226
245
|
let dir = start;
|
|
227
246
|
while (true) {
|
|
228
247
|
try {
|
|
229
|
-
|
|
248
|
+
accessSync(join(dir, "package.json"), constants.R_OK);
|
|
249
|
+
return dir;
|
|
230
250
|
} catch {}
|
|
231
251
|
const parent = resolve(dir, "..");
|
|
232
252
|
if (parent === dir) throw new Error("package root not found");
|
|
233
253
|
dir = parent;
|
|
234
254
|
}
|
|
235
|
-
}
|
|
236
|
-
|
|
255
|
+
};
|
|
256
|
+
const findTemplateDir = (start = import.meta.dirname) => {
|
|
257
|
+
const root = findPackageRoot(start);
|
|
258
|
+
const candidates = [join(root, "src", "template"), join(root, "dist", "template")];
|
|
237
259
|
for (const dir of candidates) try {
|
|
238
|
-
|
|
260
|
+
accessSync(dir, constants.R_OK);
|
|
261
|
+
return dir;
|
|
239
262
|
} catch {}
|
|
240
263
|
throw new Error(`template directory not found under ${root}`);
|
|
241
|
-
}
|
|
242
|
-
|
|
264
|
+
};
|
|
265
|
+
const findAppDir = (start = import.meta.dirname) => {
|
|
266
|
+
const root = findPackageRoot(start);
|
|
267
|
+
const candidates = [join(root, "src", "app"), join(root, "dist", "app")];
|
|
243
268
|
for (const dir of candidates) try {
|
|
244
|
-
|
|
269
|
+
accessSync(dir, constants.R_OK);
|
|
270
|
+
return dir;
|
|
245
271
|
} catch {}
|
|
246
272
|
throw new Error(`template directory not found under ${root}`);
|
|
247
|
-
}
|
|
248
|
-
|
|
273
|
+
};
|
|
274
|
+
const styleVariablesPlugin = (appDir, inputDir) => {
|
|
275
|
+
const cssVirtualModuleId = "virtual:style-variables.css";
|
|
276
|
+
const jsVirtualModuleId = "virtual:style-variables.js";
|
|
277
|
+
const resolvedCssPath = `\0${path.join(appDir, "virtual-style-variables.css")}`;
|
|
278
|
+
const resolvedJsPath = `\0${path.join(appDir, "virtual-style-variables.js")}`;
|
|
249
279
|
return {
|
|
250
280
|
name: "style-variables-plugin",
|
|
251
281
|
enforce: "pre",
|
|
@@ -255,75 +285,78 @@ const deriveParameters = ({ rawParameters, setVersion, setReleaseDate }) => {
|
|
|
255
285
|
},
|
|
256
286
|
async load(id) {
|
|
257
287
|
if (id === resolvedCssPath || id === resolvedJsPath) {
|
|
258
|
-
const configPath = path.join(appDir, "styles/config.json")
|
|
288
|
+
const configPath = path.join(appDir, "styles/config.json");
|
|
289
|
+
const configContent = fs$1.readFileSync(configPath, "utf-8");
|
|
290
|
+
const config = JSON.parse(configContent);
|
|
259
291
|
config.source = [path.join(appDir, "styles/style-tokens/**/*.json")];
|
|
260
292
|
const themePath = path.join(inputDir, "theme.json");
|
|
261
293
|
if (fs$1.existsSync(themePath)) config.source.push(themePath);
|
|
262
294
|
const sd = new StyleDictionary(config);
|
|
263
|
-
if (id === resolvedCssPath)
|
|
264
|
-
|
|
265
|
-
return files[0]?.output;
|
|
266
|
-
}
|
|
267
|
-
if (id === resolvedJsPath) {
|
|
268
|
-
const files = await sd.formatPlatform("js");
|
|
269
|
-
return files[0]?.output;
|
|
270
|
-
}
|
|
295
|
+
if (id === resolvedCssPath) return (await sd.formatPlatform("css"))[0]?.output;
|
|
296
|
+
if (id === resolvedJsPath) return (await sd.formatPlatform("js"))[0]?.output;
|
|
271
297
|
}
|
|
272
298
|
},
|
|
273
299
|
handleHotUpdate({ file, server }) {
|
|
274
|
-
const isStyleToken = file.includes("/style-tokens/")
|
|
300
|
+
const isStyleToken = file.includes("/style-tokens/");
|
|
301
|
+
const isTheme = file === path.join(inputDir, "theme.json");
|
|
275
302
|
if (!isStyleToken && !isTheme) return;
|
|
276
|
-
|
|
277
|
-
return ids.forEach((id) => {
|
|
303
|
+
[resolvedCssPath, resolvedJsPath].forEach((id) => {
|
|
278
304
|
const mod = server.moduleGraph.getModuleById(id);
|
|
279
305
|
if (mod) server.moduleGraph.invalidateModule(mod);
|
|
280
|
-
})
|
|
306
|
+
});
|
|
307
|
+
return [];
|
|
281
308
|
}
|
|
282
309
|
};
|
|
283
|
-
}
|
|
310
|
+
};
|
|
311
|
+
const htmlTransformPlugin = (title) => {
|
|
284
312
|
return {
|
|
285
313
|
name: "html-transform",
|
|
286
314
|
transformIndexHtml(html) {
|
|
287
315
|
return html.replace(/%APP_TITLE%/g, title);
|
|
288
316
|
}
|
|
289
317
|
};
|
|
290
|
-
}
|
|
318
|
+
};
|
|
319
|
+
const watchInputDirPlugin = (inputDir) => {
|
|
291
320
|
return {
|
|
292
321
|
name: "watch-input-dir",
|
|
293
322
|
configureServer(server) {
|
|
294
323
|
const watchPattern = path.join(inputDir, "**/*.{md,json,png}");
|
|
295
324
|
server.watcher.add(watchPattern);
|
|
296
325
|
const handleFileChange = (changedPath) => {
|
|
297
|
-
console.log(`Input file changed, reloading: ${path.relative(inputDir, changedPath)}`)
|
|
326
|
+
console.log(`Input file changed, reloading: ${path.relative(inputDir, changedPath)}`);
|
|
327
|
+
server.ws.send({ type: "full-reload" });
|
|
298
328
|
};
|
|
299
|
-
server.watcher.on("add", handleFileChange)
|
|
329
|
+
server.watcher.on("add", handleFileChange);
|
|
330
|
+
server.watcher.on("change", handleFileChange);
|
|
331
|
+
server.watcher.on("unlink", handleFileChange);
|
|
300
332
|
}
|
|
301
333
|
};
|
|
302
334
|
};
|
|
303
335
|
dotenv.config({ path: path.resolve(process.cwd(), ".env") });
|
|
304
|
-
|
|
305
|
-
|
|
336
|
+
var basePath = process.env.BASE_PATH || "/";
|
|
337
|
+
const generate = async (command, mode) => {
|
|
338
|
+
const inputDir = path.resolve(process.cwd(), command.input);
|
|
339
|
+
const outputDir = path.resolve(process.cwd(), command.output);
|
|
340
|
+
const inputs = await loadInputs({
|
|
306
341
|
inputPath: inputDir,
|
|
307
342
|
verbose: false
|
|
308
343
|
});
|
|
309
344
|
if (!inputs) throw new Error("Invalid DocGen input files, aborting...");
|
|
310
|
-
const { contents, rawParameters } = inputs
|
|
345
|
+
const { contents, rawParameters } = inputs;
|
|
346
|
+
const sortedPages = sortPages({ contents });
|
|
347
|
+
const parameters = deriveParameters({
|
|
311
348
|
rawParameters,
|
|
312
349
|
setVersion: command?.setVersion,
|
|
313
350
|
setReleaseDate: command?.setReleaseDate
|
|
314
|
-
})
|
|
351
|
+
});
|
|
352
|
+
const appPath = findAppDir(import.meta.dirname);
|
|
353
|
+
const baseConfig = {
|
|
315
354
|
root: appPath,
|
|
316
355
|
publicDir: inputDir,
|
|
317
356
|
base: basePath,
|
|
318
|
-
resolve: { alias: {
|
|
319
|
-
"vite-plugin-node-polyfills/shims/process": require.resolve("vite-plugin-node-polyfills/shims/process"),
|
|
320
|
-
"vite-plugin-node-polyfills/shims/buffer": require.resolve("vite-plugin-node-polyfills/shims/buffer"),
|
|
321
|
-
"vite-plugin-node-polyfills/shims/global": require.resolve("vite-plugin-node-polyfills/shims/global")
|
|
322
|
-
} },
|
|
323
357
|
plugins: [
|
|
324
|
-
nodePolyfills({ include: ["buffer"] }),
|
|
325
358
|
styleVariablesPlugin(appPath, inputDir),
|
|
326
|
-
react({ exclude: /\/src\/app\/pdf\// }),
|
|
359
|
+
react({ exclude: [/\/src\/app\/pdf\//, /\/node_modules\//] }),
|
|
327
360
|
htmlTransformPlugin(parameters.title ?? "DocGen"),
|
|
328
361
|
...mode !== "build" ? [watchInputDirPlugin(inputDir)] : []
|
|
329
362
|
],
|
|
@@ -338,22 +371,32 @@ const require = createRequire(import.meta.url), basePath = process.env.BASE_PATH
|
|
|
338
371
|
...baseConfig,
|
|
339
372
|
build: {
|
|
340
373
|
outDir: outputDir,
|
|
341
|
-
emptyOutDir: true
|
|
342
|
-
minify: false
|
|
374
|
+
emptyOutDir: true
|
|
343
375
|
}
|
|
344
376
|
});
|
|
345
377
|
else {
|
|
346
378
|
const server = await createServer(baseConfig);
|
|
347
|
-
await server.listen()
|
|
379
|
+
await server.listen();
|
|
380
|
+
server.printUrls();
|
|
348
381
|
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
382
|
+
};
|
|
383
|
+
const scaffold = async (command) => {
|
|
384
|
+
const inputDir = findTemplateDir(import.meta.dirname);
|
|
385
|
+
const outputDir = path.normalize(command.output + "/");
|
|
386
|
+
const verbose = command.verbose === true;
|
|
387
|
+
console.log(pico.green("Creating scaffold template directory"));
|
|
388
|
+
await copyDirectory(inputDir, outputDir, verbose);
|
|
389
|
+
};
|
|
390
|
+
program.version("6.4.2").usage("[command] [--option]");
|
|
391
|
+
program.command("scaffold").usage("[--option]").description("create a template input directory").option("-o, --output [path]", "path to the output directory (default: ./)", "./").option("-v, --verbose", "show verbose output including detailed errors").action((command) => {
|
|
354
392
|
scaffold(command);
|
|
355
|
-
})
|
|
393
|
+
});
|
|
394
|
+
program.command("dev").usage("[--option]").description("create a static website from an input directory").option("-i, --input [path]", "path to the input directory [default: ./]", "./").option("-o, --output [path]", "path to the output directory [default: ./output]", "./output").option("-p, --pdf", "create a PDF document").option("-s, --set-version [version]", "override parameters.version (useful for build tools) [default: false]", false).option("-R, --set-release-date [date]", "override parameters.date (useful for build tools) [default: false]", false).option("-v, --verbose", "show verbose output including detailed errors").action((command) => {
|
|
356
395
|
generate(command, "dev");
|
|
357
|
-
})
|
|
396
|
+
});
|
|
397
|
+
program.command("build").usage("[--option]").description("create a static website from an input directory").option("-i, --input [path]", "path to the input directory [default: ./]", "./").option("-o, --output [path]", "path to the output directory [default: ./output]", "./output").option("-p, --pdf", "create a PDF document").option("-s, --set-version [version]", "override parameters.version (useful for build tools) [default: false]", false).option("-R, --set-release-date [date]", "override parameters.date (useful for build tools) [default: false]", false).option("-v, --verbose", "show verbose output including detailed errors").action((command) => {
|
|
358
398
|
generate(command, "build");
|
|
359
|
-
})
|
|
399
|
+
});
|
|
400
|
+
program.parse(process.argv);
|
|
401
|
+
if (!process.argv.slice(2).length) program.help();
|
|
402
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docgen-tool",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "6.4.
|
|
4
|
+
"version": "6.4.2",
|
|
5
5
|
"description": "A tool for creating HTML and PDF documentation",
|
|
6
6
|
"bin": "./dist/cli/cli.js",
|
|
7
7
|
"files": [
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@react-pdf/renderer": "^4.3.2",
|
|
40
|
-
"@tanstack/react-router": "^1.
|
|
41
|
-
"@vitejs/plugin-react": "5.
|
|
40
|
+
"@tanstack/react-router": "^1.150.0",
|
|
41
|
+
"@vitejs/plugin-react": "5.1.2",
|
|
42
42
|
"cheerio": "^1.1.2",
|
|
43
43
|
"classnames": "^2.5.1",
|
|
44
44
|
"commander": "^14.0.2",
|
|
@@ -58,18 +58,17 @@
|
|
|
58
58
|
"rehype-raw": "^7.0.0",
|
|
59
59
|
"remark-gfm": "^4.0.1",
|
|
60
60
|
"rolldown-vite": "^7.3.1",
|
|
61
|
-
"style-dictionary": "^5.1.
|
|
62
|
-
"vite": "
|
|
63
|
-
"vite-plugin-node-polyfills": "0.22.0",
|
|
61
|
+
"style-dictionary": "^5.1.4",
|
|
62
|
+
"vite": "8.0.0-beta.8",
|
|
64
63
|
"z-schema": "^6.0.2"
|
|
65
64
|
},
|
|
66
65
|
"devDependencies": {
|
|
67
66
|
"@prettier/plugin-oxc": "^0.1.3",
|
|
68
|
-
"@types/node": "^25.0.
|
|
67
|
+
"@types/node": "^25.0.9",
|
|
69
68
|
"@types/react": "^19.2.8",
|
|
70
69
|
"ncp": "^2.0.0",
|
|
71
|
-
"oxlint": "^1.
|
|
72
|
-
"prettier": "^3.
|
|
70
|
+
"oxlint": "^1.39.0",
|
|
71
|
+
"prettier": "^3.8.0",
|
|
73
72
|
"rimraf": "^6.1.2",
|
|
74
73
|
"tsx": "^4.21.0",
|
|
75
74
|
"typescript": "^5.9.3"
|