@menapo/vicss 0.0.0-stage → 1.0.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,149 @@
1
+ import { _ as BUILT_IN_UTILITIES, _t as VicssError, dt as isScaleName, ut as isPlainObject, y as resolveSystem } from "./print-Ds6fkgio.js";
2
+ //#region src/core/snapshot.ts
3
+ /**
4
+ * The lint snapshot, `vicss.lint.json`: what the lint rules (src/lint) need
5
+ * of the design system. Lint rules run synchronously, in Oxlint or ESLint,
6
+ * so they cannot load `vicss.config.ts`, its presets and its DTCG files; the
7
+ * plugin and `vicss types` write this file next to `vicss.d.ts` instead,
8
+ * and the rules resolve the system from it with the compiler's own code.
9
+ *
10
+ * It holds the config as it merged, as data: tokens, semantic tokens, text
11
+ * styles, conditions, dark mode, strictness, palettes, `privateAccess`, the
12
+ * custom property prefix and the import sources. A utility's transform is
13
+ * code, so a utility is its name and the scale or flag its value takes.
14
+ * Private tokens are listed by path, read from `ResolvedToken.private`, in
15
+ * place of the `tokenVisibility` patterns they came from; the project root
16
+ * is recorded relative to the file, so `privateAccess` globs match the
17
+ * linted files as they match the build's modules. What no module's style
18
+ * reads (global CSS, keyframes, font faces, the reset, include and
19
+ * exclude) is left out. Key order is the config's own, which decides the
20
+ * ranks of its conditions, so one config always writes the same bytes.
21
+ */
22
+ /** The file's name; it sits next to `vicss.d.ts`. */
23
+ const SNAPSHOT_FILE = "vicss.lint.json";
24
+ /**
25
+ * Config keys no module's style reads; utilities travel on their own, and
26
+ * `tokenVisibility` as the private tokens it resolved to.
27
+ */
28
+ const LEFT_OUT = /* @__PURE__ */ new Set([
29
+ "presets",
30
+ "utilities",
31
+ "tokenVisibility",
32
+ "globalCss",
33
+ "keyframes",
34
+ "fontFaces",
35
+ "reset",
36
+ "include",
37
+ "exclude"
38
+ ]);
39
+ const BUILT_INS = new Set(Object.values(BUILT_IN_UTILITIES));
40
+ function createSnapshot(system, options = {}) {
41
+ const config = {};
42
+ for (const [key, value] of Object.entries(system.config)) if (!LEFT_OUT.has(key) && value !== void 0) config[key] = value;
43
+ const utilities = {};
44
+ for (const [name, def] of system.utilities) {
45
+ if (BUILT_INS.has(def)) continue;
46
+ utilities[name] = {
47
+ ...def.scale ? { scale: def.scale } : {},
48
+ ...def.boolean ? { boolean: true } : {}
49
+ };
50
+ }
51
+ const privateTokens = {};
52
+ for (const [scale, table] of system.tokens) {
53
+ const paths = [...table.values()].filter((t) => t.private === true).map((t) => t.path);
54
+ if (paths.length > 0) privateTokens[scale] = paths.sort();
55
+ }
56
+ return JSON.parse(JSON.stringify({
57
+ format: 1,
58
+ ...options.root !== void 0 ? { root: options.root } : {},
59
+ config,
60
+ utilities,
61
+ private: privateTokens
62
+ }));
63
+ }
64
+ /**
65
+ * The file's text: indented, so a committed snapshot diffs by token, and
66
+ * printed as the formatter prints JSON (objects expanded, a list of values
67
+ * on one line when it fits in 100 columns), so `vp fmt` and the plugin
68
+ * never rewrite each other's file.
69
+ */
70
+ function snapshotText(system, options = {}) {
71
+ return `${printJson(createSnapshot(system, options), "", "", "")}\n`;
72
+ }
73
+ const WIDTH = 100;
74
+ /** `value` on a line that starts with `indent` and `head` and ends with `tail`. */
75
+ function printJson(value, indent, head, tail) {
76
+ if (Array.isArray(value)) {
77
+ if (value.length === 0) return `${head}[]${tail}`;
78
+ const flat = value.every((item) => typeof item !== "object" || item === null);
79
+ const line = `${head}[${value.map((item) => JSON.stringify(item)).join(", ")}]${tail}`;
80
+ if (flat && indent.length + line.length <= WIDTH) return line;
81
+ const inner = `${indent} `;
82
+ return `${head}[\n${value.map((item, i) => inner + printJson(item, inner, "", i < value.length - 1 ? "," : "")).join("\n")}\n${indent}]${tail}`;
83
+ }
84
+ if (typeof value === "object" && value !== null) {
85
+ const entries = Object.entries(value);
86
+ if (entries.length === 0) return `${head}{}${tail}`;
87
+ const inner = `${indent} `;
88
+ return `${head}{\n${entries.map(([key, item], i) => inner + printJson(item, inner, `${JSON.stringify(key)}: `, i < entries.length - 1 ? "," : "")).join("\n")}\n${indent}}${tail}`;
89
+ }
90
+ return `${head}${JSON.stringify(value)}${tail}`;
91
+ }
92
+ /**
93
+ * Resolves the system a snapshot describes. A config utility becomes one
94
+ * whose transform sets nothing, so its value is checked against its scale
95
+ * and its output is not checked: the build does that. Throws a VicssError
96
+ * `SNAPSHOT` for a file of another format or one that does not resolve.
97
+ */
98
+ function readSnapshot(data) {
99
+ if (!isPlainObject(data) || typeof data.format !== "number") throw snapshotError("is not a vicss lint snapshot");
100
+ if (data.format !== 1) throw snapshotError(`has format ${data.format}, and this version of vicss reads format 1`);
101
+ if (!isPlainObject(data.config) || !isPlainObject(data.utilities)) throw snapshotError("is not a vicss lint snapshot");
102
+ const utilities = {};
103
+ for (const [name, def] of Object.entries(data.utilities)) {
104
+ const { scale, boolean } = isPlainObject(def) ? def : {};
105
+ utilities[name] = {
106
+ ...scale ? { scale } : {},
107
+ ...boolean ? { boolean } : {},
108
+ transform: () => ({})
109
+ };
110
+ }
111
+ let system;
112
+ try {
113
+ system = resolveSystem({
114
+ ...data.config,
115
+ utilities
116
+ });
117
+ } catch (error) {
118
+ if (!(error instanceof VicssError)) throw error;
119
+ throw snapshotError(`does not resolve: ${error.message}`);
120
+ }
121
+ const tokens = new Map(system.tokens);
122
+ for (const [scale, paths] of Object.entries(isPlainObject(data.private) ? data.private : {})) {
123
+ if (!isScaleName(scale) || !Array.isArray(paths)) continue;
124
+ const table = system.tokens.get(scale);
125
+ if (!table) continue;
126
+ const marked = new Map(table);
127
+ for (const path of paths) {
128
+ const token = typeof path === "string" ? table.get(path) : void 0;
129
+ if (token && !token.palette) marked.set(path, {
130
+ ...token,
131
+ private: true
132
+ });
133
+ }
134
+ tokens.set(scale, marked);
135
+ }
136
+ return {
137
+ system: {
138
+ ...system,
139
+ tokens
140
+ },
141
+ importSources: system.config.importSources ?? [],
142
+ ...typeof data.root === "string" ? { root: data.root } : {}
143
+ };
144
+ }
145
+ function snapshotError(problem) {
146
+ return new VicssError("SNAPSHOT", `${SNAPSHOT_FILE} ${problem}`, { hint: "Write it again for this version of vicss: start the dev server, or run `vicss types`." });
147
+ }
148
+ //#endregion
149
+ export { readSnapshot as n, snapshotText as r, SNAPSHOT_FILE as t };