rtgl 0.0.38 → 1.0.0-rc10
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/cli.js +113 -49
- package/package.json +5 -5
package/cli.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { build, scaffold, watch, examples } from "@rettangoli/fe/cli";
|
|
4
|
-
import { generate, report, accept } from "@rettangoli/vt/cli";
|
|
5
|
-
import { buildSite, watchSite,
|
|
3
|
+
import { build, check, scaffold, watch, examples } from "@rettangoli/fe/cli";
|
|
4
|
+
import { generate, screenshot, report, accept } from "@rettangoli/vt/cli";
|
|
5
|
+
import { buildSite, watchSite, initSite } from "@rettangoli/sites/cli";
|
|
6
6
|
import { buildSvg } from "@rettangoli/ui/cli";
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
import { readFileSync, existsSync } from "fs";
|
|
@@ -25,11 +25,14 @@ function readConfig() {
|
|
|
25
25
|
const configContent = readFileSync(configPath, "utf8");
|
|
26
26
|
return yaml.load(configContent);
|
|
27
27
|
} catch (error) {
|
|
28
|
-
|
|
29
|
-
return null;
|
|
28
|
+
throw new Error(`Error reading config file "${configPath}": ${error.message}`);
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
31
|
|
|
32
|
+
function collectValues(value, previous = []) {
|
|
33
|
+
return [...previous, value];
|
|
34
|
+
}
|
|
35
|
+
|
|
33
36
|
const program = new Command();
|
|
34
37
|
|
|
35
38
|
program
|
|
@@ -103,6 +106,41 @@ Examples:
|
|
|
103
106
|
build(options);
|
|
104
107
|
});
|
|
105
108
|
|
|
109
|
+
feCommand
|
|
110
|
+
.command("check")
|
|
111
|
+
.description("Validate frontend component file contracts")
|
|
112
|
+
.option("--format <format>", "Output format: text or json", "text")
|
|
113
|
+
.addHelpText(
|
|
114
|
+
"after",
|
|
115
|
+
`
|
|
116
|
+
|
|
117
|
+
Examples:
|
|
118
|
+
$ rettangoli fe check
|
|
119
|
+
$ rettangoli fe check --format json
|
|
120
|
+
`,
|
|
121
|
+
)
|
|
122
|
+
.action((options) => {
|
|
123
|
+
const config = readConfig();
|
|
124
|
+
|
|
125
|
+
if (!config) {
|
|
126
|
+
throw new Error("rettangoli.config.yaml not found");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (!config.fe?.dirs?.length) {
|
|
130
|
+
throw new Error("fe.dirs not found or empty in config");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const missingDirs = config.fe.dirs.filter(
|
|
134
|
+
(dir) => !existsSync(resolve(process.cwd(), dir)),
|
|
135
|
+
);
|
|
136
|
+
if (missingDirs.length > 0) {
|
|
137
|
+
throw new Error(`Directories do not exist: ${missingDirs.join(", ")}`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
options.dirs = config.fe.dirs;
|
|
141
|
+
check(options);
|
|
142
|
+
});
|
|
143
|
+
|
|
106
144
|
feCommand
|
|
107
145
|
.command("scaffold")
|
|
108
146
|
.description("Scaffold UI components")
|
|
@@ -193,12 +231,15 @@ const vtCommand = program
|
|
|
193
231
|
|
|
194
232
|
vtCommand
|
|
195
233
|
.command("generate")
|
|
196
|
-
.description("Generate
|
|
197
|
-
.option("--
|
|
198
|
-
.option("--
|
|
199
|
-
.option("--
|
|
200
|
-
.option("--
|
|
201
|
-
.
|
|
234
|
+
.description("Generate candidate HTML pages only (no screenshots)")
|
|
235
|
+
.option("--concurrency <number>", "Number of parallel capture workers", parseInt)
|
|
236
|
+
.option("--timeout <ms>", "Global capture timeout in ms", parseInt)
|
|
237
|
+
.option("--wait-event <name>", "Custom event name to mark page ready (uses event wait strategy)")
|
|
238
|
+
.option("--folder <path>", "Run only specs under folder prefix (repeatable)", collectValues, [])
|
|
239
|
+
.option("--group <section-key>", "Run only one section key from vt.sections (repeatable)", collectValues, [])
|
|
240
|
+
.option("--item <spec-path>", "Run only one spec path relative to vt/specs (repeatable)", collectValues, [])
|
|
241
|
+
.option("--headed", "Run Playwright in headed mode")
|
|
242
|
+
.action(async (options) => {
|
|
202
243
|
console.log(`rtgl v${packageJson.version}`);
|
|
203
244
|
const config = readConfig();
|
|
204
245
|
|
|
@@ -208,17 +249,49 @@ vtCommand
|
|
|
208
249
|
|
|
209
250
|
// Use vt.path from config, default to 'vt'
|
|
210
251
|
options.vtPath = config.vt?.path || "vt";
|
|
252
|
+
if (options.headed) {
|
|
253
|
+
options.headless = false;
|
|
254
|
+
}
|
|
255
|
+
options.captureScreenshots = false;
|
|
256
|
+
|
|
257
|
+
await generate(options);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
vtCommand
|
|
261
|
+
.command("screenshot")
|
|
262
|
+
.description("Generate candidate HTML pages and capture screenshots")
|
|
263
|
+
.option("--concurrency <number>", "Number of parallel capture workers", parseInt)
|
|
264
|
+
.option("--timeout <ms>", "Global capture timeout in ms", parseInt)
|
|
265
|
+
.option("--wait-event <name>", "Custom event name to mark page ready (uses event wait strategy)")
|
|
266
|
+
.option("--folder <path>", "Run only specs under folder prefix (repeatable)", collectValues, [])
|
|
267
|
+
.option("--group <section-key>", "Run only one section key from vt.sections (repeatable)", collectValues, [])
|
|
268
|
+
.option("--item <spec-path>", "Run only one spec path relative to vt/specs (repeatable)", collectValues, [])
|
|
269
|
+
.option("--headed", "Run Playwright in headed mode")
|
|
270
|
+
.action(async (options) => {
|
|
271
|
+
console.log(`rtgl v${packageJson.version}`);
|
|
272
|
+
const config = readConfig();
|
|
273
|
+
|
|
274
|
+
if (!config) {
|
|
275
|
+
throw new Error("rettangoli.config.yaml not found");
|
|
276
|
+
}
|
|
211
277
|
|
|
212
|
-
|
|
278
|
+
options.vtPath = config.vt?.path || "vt";
|
|
279
|
+
if (options.headed) {
|
|
280
|
+
options.headless = false;
|
|
281
|
+
}
|
|
282
|
+
await screenshot(options);
|
|
213
283
|
});
|
|
214
284
|
|
|
215
285
|
vtCommand
|
|
216
286
|
.command("report")
|
|
217
287
|
.description("Create reports")
|
|
218
|
-
.option("--compare-method <method>", "Comparison method: pixelmatch or md5"
|
|
219
|
-
.option("--color-threshold <number>", "Color threshold for pixelmatch (0-1)", parseFloat
|
|
220
|
-
.option("--diff-threshold <number>", "Max diff pixels percentage to pass (0-100)", parseFloat
|
|
221
|
-
.
|
|
288
|
+
.option("--compare-method <method>", "Comparison method: pixelmatch or md5")
|
|
289
|
+
.option("--color-threshold <number>", "Color threshold for pixelmatch (0-1)", parseFloat)
|
|
290
|
+
.option("--diff-threshold <number>", "Max diff pixels percentage to pass (0-100)", parseFloat)
|
|
291
|
+
.option("--folder <path>", "Compare only screenshots under folder prefix (repeatable)", collectValues, [])
|
|
292
|
+
.option("--group <section-key>", "Compare only one section key from vt.sections (repeatable)", collectValues, [])
|
|
293
|
+
.option("--item <spec-path>", "Compare only one spec path relative to vt/specs (repeatable)", collectValues, [])
|
|
294
|
+
.action(async (options) => {
|
|
222
295
|
const config = readConfig();
|
|
223
296
|
|
|
224
297
|
if (!config) {
|
|
@@ -226,18 +299,21 @@ vtCommand
|
|
|
226
299
|
}
|
|
227
300
|
|
|
228
301
|
const vtPath = config.vt?.path || "vt";
|
|
229
|
-
report({
|
|
302
|
+
await report({
|
|
230
303
|
vtPath,
|
|
231
304
|
compareMethod: options.compareMethod,
|
|
232
305
|
colorThreshold: options.colorThreshold,
|
|
233
306
|
diffThreshold: options.diffThreshold,
|
|
307
|
+
folder: options.folder,
|
|
308
|
+
group: options.group,
|
|
309
|
+
item: options.item,
|
|
234
310
|
});
|
|
235
311
|
});
|
|
236
312
|
|
|
237
313
|
vtCommand
|
|
238
314
|
.command("accept")
|
|
239
315
|
.description("Accept changes")
|
|
240
|
-
.action(() => {
|
|
316
|
+
.action(async () => {
|
|
241
317
|
const config = readConfig();
|
|
242
318
|
|
|
243
319
|
if (!config) {
|
|
@@ -245,7 +321,7 @@ vtCommand
|
|
|
245
321
|
}
|
|
246
322
|
|
|
247
323
|
const vtPath = config.vt?.path || "vt";
|
|
248
|
-
accept({ vtPath });
|
|
324
|
+
await accept({ vtPath });
|
|
249
325
|
});
|
|
250
326
|
|
|
251
327
|
const sitesCommand = program.command("sites").description("Rettangoli Sites");
|
|
@@ -264,23 +340,19 @@ sitesCommand
|
|
|
264
340
|
sitesCommand
|
|
265
341
|
.command("build")
|
|
266
342
|
.description("Build the site")
|
|
267
|
-
.option("-r, --
|
|
268
|
-
.option("
|
|
269
|
-
.option("-
|
|
343
|
+
.option("-r, --root-dir <path>", "Path to root directory", "./")
|
|
344
|
+
.option("--rootDir <path>", "Deprecated alias for --root-dir")
|
|
345
|
+
.option("-o, --output-path <path>", "Path to destination directory", "./_site")
|
|
346
|
+
.option("--outputPath <path>", "Deprecated alias for --output-path")
|
|
347
|
+
.option("-q, --quiet", "Suppress non-error logs")
|
|
270
348
|
.action(async (options) => {
|
|
271
|
-
console.log("Building site with options:", options);
|
|
272
349
|
await buildSite({
|
|
273
350
|
rootDir: options.rootDir,
|
|
274
351
|
outputPath: options.outputPath,
|
|
352
|
+
quiet: !!options.quiet,
|
|
275
353
|
});
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
// If screenshots option is enabled, run screenshot command
|
|
279
|
-
if (options.screenshots) {
|
|
280
|
-
console.log("Capturing screenshots...");
|
|
281
|
-
await screenshotCommand({
|
|
282
|
-
rootDir: options.rootDir,
|
|
283
|
-
});
|
|
354
|
+
if (!options.quiet) {
|
|
355
|
+
console.log("Build completed successfully!");
|
|
284
356
|
}
|
|
285
357
|
});
|
|
286
358
|
|
|
@@ -288,27 +360,19 @@ sitesCommand
|
|
|
288
360
|
.command("watch")
|
|
289
361
|
.description("Watch and rebuild site on changes")
|
|
290
362
|
.option("-p, --port <port>", "The port to use", parseInt, 3001)
|
|
291
|
-
.option("-r, --
|
|
292
|
-
.option("
|
|
363
|
+
.option("-r, --root-dir <path>", "Path to root directory", ".")
|
|
364
|
+
.option("--rootDir <path>", "Deprecated alias for --root-dir")
|
|
365
|
+
.option("-o, --output-path <path>", "Path to destination directory", "./_site")
|
|
366
|
+
.option("--outputPath <path>", "Deprecated alias for --output-path")
|
|
367
|
+
.option("--reload-mode <mode>", "Reload mode: body (hot body replacement) or full (full-page reload)", "body")
|
|
368
|
+
.option("-q, --quiet", "Suppress non-error logs")
|
|
293
369
|
.action(async (options) => {
|
|
294
|
-
console.log("Starting watch mode with options:", options);
|
|
295
370
|
watchSite({
|
|
296
371
|
port: options.port,
|
|
297
372
|
rootDir: options.rootDir,
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
sitesCommand
|
|
303
|
-
.command("screenshot")
|
|
304
|
-
.description("Capture screenshots of all pages")
|
|
305
|
-
.option("-p, --port <port>", "The port to use for temp server", parseInt, 3001)
|
|
306
|
-
.option("-r, --rootDir <path>", "Path to root directory", ".")
|
|
307
|
-
.action(async (options) => {
|
|
308
|
-
console.log("Capturing screenshots with options:", options);
|
|
309
|
-
await screenshotCommand({
|
|
310
|
-
port: options.port,
|
|
311
|
-
rootDir: options.rootDir,
|
|
373
|
+
outputPath: options.outputPath,
|
|
374
|
+
reloadMode: options.reloadMode,
|
|
375
|
+
quiet: !!options.quiet,
|
|
312
376
|
});
|
|
313
377
|
});
|
|
314
378
|
|
|
@@ -349,4 +413,4 @@ Examples:
|
|
|
349
413
|
buildSvg(options);
|
|
350
414
|
});
|
|
351
415
|
|
|
352
|
-
program.
|
|
416
|
+
await program.parseAsync();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rtgl",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "1.0.0-rc10",
|
|
4
4
|
"description": "CLI tool for Rettangoli - A frontend framework and development toolkit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"commander": "^14.0.0",
|
|
49
49
|
"js-yaml": "^4.1.0",
|
|
50
|
-
"@rettangoli/fe": "0.0
|
|
51
|
-
"@rettangoli/sites": "0.
|
|
52
|
-
"@rettangoli/vt": "0.0
|
|
53
|
-
"@rettangoli/ui": "0.
|
|
50
|
+
"@rettangoli/fe": "1.0.0-rc3",
|
|
51
|
+
"@rettangoli/sites": "1.0.0-rc2",
|
|
52
|
+
"@rettangoli/vt": "1.0.0-rc4",
|
|
53
|
+
"@rettangoli/ui": "1.0.0-rc4"
|
|
54
54
|
}
|
|
55
55
|
}
|