@domandigital/craft 0.6.0 → 0.8.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.
@@ -0,0 +1,112 @@
1
+ import {
2
+ snapshotUrl
3
+ } from "./chunk-Q4MN3OXF.js";
4
+ import {
5
+ describeTypicality,
6
+ loadNull,
7
+ typicality
8
+ } from "./chunk-K253ZXB3.js";
9
+ import {
10
+ SOURCE_FILE,
11
+ finish,
12
+ loadExceptions,
13
+ parseFlags,
14
+ readPaths
15
+ } from "./chunk-X65RDW65.js";
16
+ import {
17
+ fingerprint
18
+ } from "./chunk-OGSYVCMU.js";
19
+ import {
20
+ SNAPSHOT_VERSION,
21
+ auditSnapshot,
22
+ scanSource
23
+ } from "./chunk-CZHRNPDD.js";
24
+
25
+ // src/audit/cli.ts
26
+ import { existsSync, readFileSync, writeFileSync } from "fs";
27
+ import { resolve } from "path";
28
+ var fmt = (o) => o ? `oklch(${o.l.toFixed(3)} ${o.c.toFixed(3)} ${o.h.toFixed(1)})` : "none";
29
+ function describeFingerprint(fp) {
30
+ return [
31
+ "Fingerprint",
32
+ ` accent ${fmt(fp.accent)}`,
33
+ ` ground ${fmt(fp.ground)}`,
34
+ ` display ${fp.display.family} (${fp.display.class})`,
35
+ ` body ${fp.body.family} (${fp.body.class})`,
36
+ ` roundness ${fp.roundness === null ? "no buttons" : fp.roundness.toFixed(2)}`,
37
+ ` motion ${Math.round(fp.motion * 100)}% of sections below the fold reveal on scroll`,
38
+ ` effects ${fp.effects.join(", ") || "none"}`,
39
+ ` layout ${fp.layout.join(" > ") || "none"}`
40
+ ].join("\n");
41
+ }
42
+ function merge(a, b) {
43
+ const byTell = { ...a.summary.byTell };
44
+ for (const [k, v] of Object.entries(b.summary.byTell)) byTell[k] = (byTell[k] ?? 0) + v;
45
+ return {
46
+ catalogueVersion: a.catalogueVersion,
47
+ findings: [...a.findings, ...b.findings],
48
+ rejectedExceptions: a.rejectedExceptions,
49
+ excepted: [...a.excepted, ...b.excepted],
50
+ suppressed: [...a.suppressed, ...b.suppressed],
51
+ summary: {
52
+ files: a.summary.files + b.summary.files,
53
+ findings: a.summary.findings + b.summary.findings,
54
+ byGeneration: { 1: a.summary.byGeneration[1] + b.summary.byGeneration[1], 2: a.summary.byGeneration[2] + b.summary.byGeneration[2], 3: a.summary.byGeneration[3] + b.summary.byGeneration[3] },
55
+ byTell,
56
+ blocking: a.summary.blocking + b.summary.blocking
57
+ }
58
+ };
59
+ }
60
+ function readSnapshot(path) {
61
+ const data = JSON.parse(readFileSync(path, "utf8"));
62
+ if (data.version !== SNAPSHOT_VERSION) throw new Error(`${path} is snapshot version ${String(data.version)}; this craft reads ${SNAPSHOT_VERSION}`);
63
+ return data;
64
+ }
65
+ async function runAudit(command, args, io) {
66
+ try {
67
+ const flags = parseFlags(args);
68
+ if (typeof flags === "string") throw new Error(flags);
69
+ const target = flags.positional[0];
70
+ if (!target) throw new Error(`usage: craft ${command} <url${command === "audit" ? " | snapshot.json" : ""}>`);
71
+ const viewport = flags.width || flags.height ? { width: Number(flags.width ?? 1440), height: Number(flags.height ?? 900) } : void 0;
72
+ const local = resolve(io.cwd, target);
73
+ const snapshot = command === "audit" && /\.json$/i.test(target) && existsSync(local) ? readSnapshot(local) : await snapshotUrl(target, { viewport });
74
+ if (flags.out) writeFileSync(resolve(io.cwd, flags.out), `${JSON.stringify(snapshot, null, 2)}
75
+ `);
76
+ if (command === "snapshot") {
77
+ if (!flags.out) io.out(JSON.stringify(snapshot, null, 2));
78
+ else io.out(`craft snapshot: ${snapshot.url} saved to ${flags.out}`);
79
+ return 0;
80
+ }
81
+ const exceptions = loadExceptions(flags, flags.repo ? resolve(io.cwd, flags.repo) : io.cwd);
82
+ let report = auditSnapshot(snapshot, { exceptions });
83
+ if (flags.repo) {
84
+ const repo = resolve(io.cwd, flags.repo);
85
+ report = merge(scanSource(readPaths(["."], repo, SOURCE_FILE), { exceptions }), report);
86
+ }
87
+ const fp = fingerprint(snapshot);
88
+ const nulls = flags.null ? flags.null.split(",").map((p) => loadNull(p.trim(), io.cwd)) : [];
89
+ const typical = nulls.length ? typicality(fp, nulls.flatMap((m, i) => m.runs.map((r) => nulls.length > 1 ? { ...r, id: `${i + 1}/${r.id}` } : r))) : null;
90
+ if (flags.json) {
91
+ io.out(JSON.stringify({ report, fingerprint: fp, typicality: typical, snapshot: flags.out ?? null }, null, 2));
92
+ return report.summary.blocking > 0 || flags.strict && report.summary.findings > 0 ? 1 : 0;
93
+ }
94
+ const code = finish(report, { ...flags, json: false }, `craft audit ${snapshot.url}`, io);
95
+ io.out("");
96
+ io.out(describeFingerprint(fp));
97
+ if (typical) {
98
+ io.out("");
99
+ io.out(describeTypicality(typical, nulls.reduce((s, m) => s + m.runs.length, 0), nulls.length));
100
+ }
101
+ return code;
102
+ } catch (error) {
103
+ io.err(`craft: ${error.message}`);
104
+ return 2;
105
+ }
106
+ }
107
+
108
+ export {
109
+ describeFingerprint,
110
+ merge,
111
+ runAudit
112
+ };