@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.
- package/LICENSE +21 -0
- package/README.md +627 -2
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1311 -0
- package/dist/config-loader-DzP68Snn.js +162 -0
- package/dist/config-loader-pLzP9par.js +1 -0
- package/dist/config.d.ts +821 -0
- package/dist/config.js +2690 -0
- package/dist/index.d.ts +1471 -0
- package/dist/index.js +369 -0
- package/dist/lint.d.ts +114 -0
- package/dist/lint.js +0 -0
- package/dist/pool-BGXMhLfL.js +2942 -0
- package/dist/print-Ds6fkgio.js +5093 -0
- package/dist/snapshot-BQb8ZmSV.js +149 -0
- package/dist/theme-C-0LpsJx.js +2437 -0
- package/dist/types-file-R_knFzME.js +2481 -0
- package/dist/vite.d.ts +245 -0
- package/dist/vite.js +1926 -0
- package/dist/worker.d.ts +1 -0
- package/dist/worker.js +113 -0
- package/package.json +66 -3
package/dist/index.js
ADDED
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
//#region src/runtime/merge.ts
|
|
2
|
+
/**
|
|
3
|
+
* S2 over the arguments, arrays flattened and a dynamic style read as its
|
|
4
|
+
* constant style: the classes kept as they are, in order and once each, and
|
|
5
|
+
* merge id → class. An argument's ids replace their own id and drop the ids
|
|
6
|
+
* below them in their chain (`p` drops `p-b-s`, `md:p` does not); one
|
|
7
|
+
* argument is an already merged set, whose ids never clear each other. The
|
|
8
|
+
* recipe resolver and the compiler's fold share it.
|
|
9
|
+
*/
|
|
10
|
+
const merge = (args) => {
|
|
11
|
+
const names = /* @__PURE__ */ new Set();
|
|
12
|
+
const kept = /* @__PURE__ */ new Map();
|
|
13
|
+
const add = (list) => list.split(/\s+/).map((name) => name && names.add(name));
|
|
14
|
+
for (let arg of args.flat(1 / 0)) if (arg = arg && (arg.$c ?? arg)) if (arg.split) add(arg);
|
|
15
|
+
else {
|
|
16
|
+
for (const id of kept.keys()) for (const key in arg) if (id[key.length] == "-" && id.startsWith(key) && !id.includes(":", key.length)) {
|
|
17
|
+
kept.delete(id);
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
for (const id in arg) if (id == "$n") add(arg[id]);
|
|
21
|
+
else kept.set(id, arg[id]);
|
|
22
|
+
}
|
|
23
|
+
return [names, kept];
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The class attribute: the classes kept as they are, then one class per id
|
|
27
|
+
* in id order (S3), so folded, server and client output agree. The ids sort
|
|
28
|
+
* alone: sorting `[id, class]` entries would join each into a string per
|
|
29
|
+
* comparison, five times the cost.
|
|
30
|
+
*/
|
|
31
|
+
const join = ([names, kept]) => [...names, ...[...kept.keys()].sort().map((id) => kept.get(id))].join(" ");
|
|
32
|
+
const cache = /* @__PURE__ */ new Map();
|
|
33
|
+
let nodes = 0;
|
|
34
|
+
let vars;
|
|
35
|
+
/**
|
|
36
|
+
* One argument: the trie node below `node` for it, or 0 once the call cannot
|
|
37
|
+
* be cached. Falsy arguments contribute nothing, so they add no level.
|
|
38
|
+
*/
|
|
39
|
+
const walk = (node, arg) => {
|
|
40
|
+
if (!arg) return node;
|
|
41
|
+
const known = node && node.get(arg);
|
|
42
|
+
if (known) return known;
|
|
43
|
+
if (arg.map) return arg.reduce(walk, 0);
|
|
44
|
+
if (arg.$c) {
|
|
45
|
+
Object.assign(vars, arg.$s);
|
|
46
|
+
return walk(node, arg.$c);
|
|
47
|
+
}
|
|
48
|
+
return node && (nodes++, node.set(arg, /* @__PURE__ */ new Map()).get(arg));
|
|
49
|
+
};
|
|
50
|
+
/** The merged class attribute, cached per argument identity; `style` collects the custom properties. */
|
|
51
|
+
const classes = (args, style) => {
|
|
52
|
+
if (nodes >> 10) {
|
|
53
|
+
cache.clear();
|
|
54
|
+
nodes = 0;
|
|
55
|
+
}
|
|
56
|
+
vars = style;
|
|
57
|
+
return (args.reduce(walk, cache) || {}).r ??= join(merge(args));
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Attributes for React and Preact. In other frameworks the plugin points
|
|
61
|
+
* `sx` at the function of their shape, so its type is the project's
|
|
62
|
+
* (`Register`, types.ts).
|
|
63
|
+
*/
|
|
64
|
+
const sx$1 = (...args) => {
|
|
65
|
+
const style = {};
|
|
66
|
+
const attrs = { className: classes(args, style) };
|
|
67
|
+
for (const _ in style) attrs.style = style;
|
|
68
|
+
return attrs;
|
|
69
|
+
};
|
|
70
|
+
/** Attributes for Solid and Vue: `style` as an object. */
|
|
71
|
+
const sxClass = (...args) => {
|
|
72
|
+
const style = {};
|
|
73
|
+
const attrs = { class: classes(args, style) };
|
|
74
|
+
for (const _ in style) attrs.style = style;
|
|
75
|
+
return attrs;
|
|
76
|
+
};
|
|
77
|
+
/** Attributes for Svelte, Astro and vanilla JS: `style` as `a:b;c:d`. */
|
|
78
|
+
const sxString = (...args) => {
|
|
79
|
+
const style = {};
|
|
80
|
+
const attrs = { class: classes(args, style) };
|
|
81
|
+
const text = Object.entries(style).filter(([, value]) => value != null && value !== false && value !== "").map((entry) => entry.join(":")).join(";");
|
|
82
|
+
if (text) attrs.style = text;
|
|
83
|
+
return attrs;
|
|
84
|
+
};
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/runtime/uncompiled.ts
|
|
87
|
+
const notCompiled = (name) => {
|
|
88
|
+
throw new Error(`vicss: ${name}() was not compiled. Add the plugin from "@menapo/vicss/vite" to the Vite config: plugins: [vicss()].`);
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* A style object compiled to a style (merge id → class) that records the
|
|
92
|
+
* keys it sets; a function style compiles to a function returning that
|
|
93
|
+
* style and the custom properties its classes read. `{ name: "card" }` adds
|
|
94
|
+
* the class `card` as it is.
|
|
95
|
+
*/
|
|
96
|
+
const css = () => notCompiled("css");
|
|
97
|
+
function recipe() {
|
|
98
|
+
return notCompiled("recipe");
|
|
99
|
+
}
|
|
100
|
+
function theme() {
|
|
101
|
+
return notCompiled("theme");
|
|
102
|
+
}
|
|
103
|
+
function group() {
|
|
104
|
+
return notCompiled("group");
|
|
105
|
+
}
|
|
106
|
+
function peer() {
|
|
107
|
+
return notCompiled("peer");
|
|
108
|
+
}
|
|
109
|
+
function keyframes() {
|
|
110
|
+
return notCompiled("keyframes");
|
|
111
|
+
}
|
|
112
|
+
function token() {
|
|
113
|
+
return notCompiled("token");
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region src/runtime/recipe.ts
|
|
117
|
+
/**
|
|
118
|
+
* The recipe resolver (PLAN §4.4, §5.7): what a compiled `recipe()` becomes,
|
|
119
|
+
* `__vxRecipe(table)`, or `__vxRecipe(table, __vxResponsive)` for a recipe
|
|
120
|
+
* with responsive variants. The compiler did the styling: every cell of the
|
|
121
|
+
* table is a compiled style (merge id → class), so a call chooses cells and
|
|
122
|
+
* merges them with `sx`'s rule, in the order a style object would be assigned: base,
|
|
123
|
+
* each variant in declaration order, then the compounds that hold. Literal
|
|
124
|
+
* calls fold at build time through `resolveRecipe` in src/core/recipe.ts,
|
|
125
|
+
* which must agree with this file class for class. Bytes matter more than
|
|
126
|
+
* elegance: tests/runtime/size.test.ts holds both functions to a budget, and
|
|
127
|
+
* an app without responsive recipes never bundles `__vxResponsive`.
|
|
128
|
+
*
|
|
129
|
+
* The table (`RecipeTable` below; src/core/recipe.ts writes it):
|
|
130
|
+
*
|
|
131
|
+
* - `k`: variant names in declaration order; `s`: slot names, in slot recipes.
|
|
132
|
+
* - `b`, `v[variant][value]`: base and variant styles. A cell is a style,
|
|
133
|
+
* or a style per slot in a slot recipe.
|
|
134
|
+
* - `c`: compounds in order, `[when, classes, ranges?, cut?]`; `when` lists
|
|
135
|
+
* the values each named variant must have, as strings (`"true"`).
|
|
136
|
+
* - `d`: defaults as strings, `"false"` for a boolean variant without one.
|
|
137
|
+
* - `q`: `[conditions, breakpoints]`, the conditions a responsive prop may
|
|
138
|
+
* set (`md`, `containerMd`) in ascending rank, of which the first
|
|
139
|
+
* `breakpoints` are breakpoints and the rest container sizes.
|
|
140
|
+
* - `r[variant][value][condition]`: a responsive variant's value under each
|
|
141
|
+
* of those conditions. Every responsive variant has an entry, in
|
|
142
|
+
* declaration order.
|
|
143
|
+
* - `ranges[piece]`: a compound under the range condition of each piece of
|
|
144
|
+
* the width axis, keyed by its bounds (`",md"` below md, `"md,lg"`, `"lg,"`
|
|
145
|
+
* from lg, `"containerMd,"`); `cut` lists the responsive variants whose
|
|
146
|
+
* conditions cut the axis into the pieces it is evaluated on.
|
|
147
|
+
* - `f`, in dev only: each flattened base's atoms, as a style, by its class
|
|
148
|
+
* (the cell's `$b`, src/core/flatten.ts), for `flatBases`.
|
|
149
|
+
*/
|
|
150
|
+
const warn = (message) => console.warn("vicss: " + message);
|
|
151
|
+
/**
|
|
152
|
+
* Dev only: the atoms of every flattened base a resolver was made with, by
|
|
153
|
+
* class, which `sx()`'s dev variant reads (runtime/dev.ts). Production
|
|
154
|
+
* builds drop it with the branch that fills it.
|
|
155
|
+
*/
|
|
156
|
+
const flatBases = {};
|
|
157
|
+
const __vxRecipe = (t, x) => {
|
|
158
|
+
const { k: keys, d: defaults, v: variants } = t;
|
|
159
|
+
const memo = /* @__PURE__ */ new Map();
|
|
160
|
+
if (process.env.NODE_ENV != "production") Object.assign(flatBases, t.f);
|
|
161
|
+
return Object.assign((props = {}) => {
|
|
162
|
+
const id = JSON.stringify(keys.map((key) => props[key] ?? defaults[key]));
|
|
163
|
+
let result = memo.get(id);
|
|
164
|
+
if (!result) {
|
|
165
|
+
const values = {};
|
|
166
|
+
const cells = [t.b];
|
|
167
|
+
for (const key of keys) {
|
|
168
|
+
let value = props[key] ?? defaults[key];
|
|
169
|
+
if (typeof value == "object") {
|
|
170
|
+
if (process.env.NODE_ENV != "production" && !t.r?.[key]) warn(`\`${key}\` is not a responsive variant; its base value applies.`);
|
|
171
|
+
value = value.base ?? defaults[key];
|
|
172
|
+
}
|
|
173
|
+
cells.push(variants[key][values[key] = "" + value]);
|
|
174
|
+
}
|
|
175
|
+
const add = x?.(t, props, values, cells);
|
|
176
|
+
for (const compound of t.c) if (add) add(compound);
|
|
177
|
+
else if (Object.keys(compound[0]).every((key) => compound[0][key].includes(values[key]))) cells.push(compound[1]);
|
|
178
|
+
const slot = (name) => Object.fromEntries(merge(cells.map((cell) => typeof cell == "object" && (name ? cell[name] : cell)))[1]);
|
|
179
|
+
result = t.s ? Object.fromEntries(t.s.map((name) => [name, slot(name)])) : slot();
|
|
180
|
+
if (process.env.NODE_ENV != "production") Object.freeze(result);
|
|
181
|
+
if (memo.size >> 10) memo.clear();
|
|
182
|
+
memo.set(id, result);
|
|
183
|
+
}
|
|
184
|
+
return result;
|
|
185
|
+
}, {
|
|
186
|
+
variantKeys: keys,
|
|
187
|
+
splitProps: (props) => {
|
|
188
|
+
const split = [{}, {}];
|
|
189
|
+
for (const key in props) split[keys.includes(key) ? 0 : 1][key] = props[key];
|
|
190
|
+
return split;
|
|
191
|
+
},
|
|
192
|
+
schema: {
|
|
193
|
+
variants: Object.fromEntries(keys.map((key) => [key, Object.keys(variants[key])])),
|
|
194
|
+
defaults
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Responsive props (PLAN §4.4): each condition a prop sets adds its value's
|
|
200
|
+
* `r` cell, in rank order, so values stack mobile-first. A compound that has
|
|
201
|
+
* ranges is evaluated on each piece of the width axis, cut at the conditions
|
|
202
|
+
* its `cut` variants' props set, with the values in effect there, and adds
|
|
203
|
+
* its classes under the range condition of each piece where it holds: that
|
|
204
|
+
* range outranks every condition that holds anywhere in the piece. `ranges`
|
|
205
|
+
* keys a piece by its bounds: `",md"` below md, `"md,lg"`, `"lg,"` from lg.
|
|
206
|
+
*/
|
|
207
|
+
const __vxResponsive = (t, props, values, cells) => {
|
|
208
|
+
const [all, breakpoints] = t.q;
|
|
209
|
+
const r = t.r;
|
|
210
|
+
/** The value `key`'s prop sets under condition `name`; `key` is a responsive variant. */
|
|
211
|
+
const at = (key, name) => props[key]?.["_" + name];
|
|
212
|
+
for (const key in r) {
|
|
213
|
+
if (process.env.NODE_ENV != "production" && typeof props[key] == "object") {
|
|
214
|
+
for (const name in props[key]) if (name != "base" && !(name[0] == "_" && all.includes(name.slice(1)))) warn(`\`${name}\` is not a breakpoint or container condition of \`${key}\`; it is ignored. A recipe takes those of the design system it was compiled with: a library's, its own.`);
|
|
215
|
+
}
|
|
216
|
+
for (const name of all) if (at(key, name) != null) cells.push(r[key][at(key, name)]?.[name]);
|
|
217
|
+
}
|
|
218
|
+
return ([when, classes, ranges, cut = []]) => {
|
|
219
|
+
const current = { ...values };
|
|
220
|
+
const points = all.filter((name) => cut.some((key) => at(key, name) != null));
|
|
221
|
+
const n = points.length;
|
|
222
|
+
const held = ["", ...points].map((point) => (cut.map((key) => current[key] = "" + (at(key, point) ?? current[key])), Object.keys(when).every((key) => when[key].includes(current[key]))));
|
|
223
|
+
if (!n) return held[0] && cells.push(classes);
|
|
224
|
+
if (all.indexOf(points[n - 1]) < breakpoints) return held.map((holds, i) => holds && cells.push(ranges[[points[i - 1], points[i]] + ""]));
|
|
225
|
+
let i = n;
|
|
226
|
+
if (all.indexOf(points[0]) >= breakpoints) for (; i >= 0 && held[i]; i--) cells.push(i ? ranges[points[i - 1] + ","] : classes);
|
|
227
|
+
if (process.env.NODE_ENV != "production" && held.slice(0, i + 1).includes(true)) warn(`a compound variant on ${Object.keys(when).join(", ")} holds where no breakpoint or container condition expresses; it is left out there.`);
|
|
228
|
+
};
|
|
229
|
+
};
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/runtime/dev.ts
|
|
232
|
+
/**
|
|
233
|
+
* Dev only (PLAN §5.14): the compiler rewrites a runtime `sx()` call to the
|
|
234
|
+
* variant of its module's shape (§5.12), so the element names the source
|
|
235
|
+
* line that styled it, and wraps a function style's runtime values in a
|
|
236
|
+
* check. Builds never reference them, so they cost production bundles
|
|
237
|
+
* nothing.
|
|
238
|
+
*/
|
|
239
|
+
/**
|
|
240
|
+
* The arguments' compiled styles, nested arrays flattened and a dynamic
|
|
241
|
+
* style's constant one taken: each one merged apart, as `sx()` merges them.
|
|
242
|
+
* Classes of the app's own (strings) set no merge id.
|
|
243
|
+
*/
|
|
244
|
+
const styles = (args) => args.flat(1 / 0).flatMap((arg) => arg && typeof arg == "object" ? [arg.$c ?? arg] : []);
|
|
245
|
+
/**
|
|
246
|
+
* The classes under one reserved id among the arguments (`$t`, a theme,
|
|
247
|
+
* core/theme.ts; `$b`, a flattened base, core/flatten.ts), in the order of
|
|
248
|
+
* their last appearance: the last one is the one kept.
|
|
249
|
+
*/
|
|
250
|
+
const lastOf = (records, id) => {
|
|
251
|
+
const found = /* @__PURE__ */ new Set();
|
|
252
|
+
for (const record of records) {
|
|
253
|
+
const name = record[id];
|
|
254
|
+
if (name === void 0) continue;
|
|
255
|
+
found.delete(name);
|
|
256
|
+
found.add(name);
|
|
257
|
+
}
|
|
258
|
+
return [...found];
|
|
259
|
+
};
|
|
260
|
+
const withoutBase = (record) => {
|
|
261
|
+
const { $b: _, ...rest } = record;
|
|
262
|
+
return rest;
|
|
263
|
+
};
|
|
264
|
+
const classesOf = (args) => new Set(merge(args)[1].values());
|
|
265
|
+
/**
|
|
266
|
+
* The classes of earlier arguments that the flattened base `base` would
|
|
267
|
+
* clear, or beat by tier, as atoms and, applied under every class of its
|
|
268
|
+
* element, cannot: core/flatten.ts's `shadowedByEarlier`, with the runtime
|
|
269
|
+
* merge.
|
|
270
|
+
*/
|
|
271
|
+
const shadowed = (records, base) => {
|
|
272
|
+
const atoms = flatBases[base];
|
|
273
|
+
const at = records.findLastIndex((record) => record.$b === base);
|
|
274
|
+
if (atoms === void 0 || at < 1) return [];
|
|
275
|
+
const without = records.map(withoutBase);
|
|
276
|
+
const own = Object.fromEntries(merge([atoms, without[at]])[1]);
|
|
277
|
+
const atomic = classesOf([
|
|
278
|
+
...without.slice(0, at),
|
|
279
|
+
own,
|
|
280
|
+
...without.slice(at + 1)
|
|
281
|
+
]);
|
|
282
|
+
const flattened = classesOf([atoms, ...without]);
|
|
283
|
+
const lost = Object.entries(atoms).filter(([, name]) => atomic.has(name) && !flattened.has(name)).map(([id]) => id);
|
|
284
|
+
const out = /* @__PURE__ */ new Set();
|
|
285
|
+
for (const record of without.slice(0, at)) for (const [id, name] of Object.entries(record)) if (lost.some((other) => other == id || other.startsWith(id + "-")) || flattened.has(name) && !atomic.has(name)) out.add(name);
|
|
286
|
+
return [...out].sort();
|
|
287
|
+
};
|
|
288
|
+
/**
|
|
289
|
+
* The shape's attributes plus `data-vx-src="src/Card.tsx:12"`. Two themes,
|
|
290
|
+
* or two flattened recipe bases, among the arguments warn: one element
|
|
291
|
+
* keeps the last (core/theme.ts, core/flatten.ts); so does an earlier
|
|
292
|
+
* argument a flattened base cannot override.
|
|
293
|
+
*/
|
|
294
|
+
const withSource = (shape) => (src, ...args) => {
|
|
295
|
+
const records = styles(args);
|
|
296
|
+
const themes = lastOf(records, "$t");
|
|
297
|
+
if (themes.length > 1) {
|
|
298
|
+
const lost = themes.slice(0, -1).map((name) => `\`${name}\``);
|
|
299
|
+
console.warn(`vicss: ${src}: sx() keeps one theme per element, the last (\`${themes.at(-1)}\`): ${lost.join(", ")} ${lost.length === 1 ? "is" : "are"} dropped. Write one theme() with every override, or apply the themes to nested elements.`);
|
|
300
|
+
}
|
|
301
|
+
const bases = lastOf(records, "$b");
|
|
302
|
+
if (bases.length > 1) {
|
|
303
|
+
const lost = bases.slice(0, -1).map((name) => `\`${name}\``);
|
|
304
|
+
console.warn(`vicss: ${src}: sx() keeps one flattened recipe base per element, the last (\`${bases.at(-1)}\`): ${lost.join(", ")} ${lost.length === 1 ? "is" : "are"} dropped. Flatten one of the recipes only (\`flatten: false\` on the other), or apply them to nested elements.`);
|
|
305
|
+
} else if (bases.length === 1) {
|
|
306
|
+
const lost = shadowed(records, bases[0]).map((name) => `\`${name}\``);
|
|
307
|
+
if (lost.length > 0) console.warn(`vicss: ${src}: sx() applies the flattened recipe base \`${bases[0]}\` under every class of the element: ${lost.join(", ")}, from an earlier argument, ${lost.length === 1 ? "wins" : "win"} over what the base sets, which an atomic base would override. Pass the recipe's result first (sx(recipe(…), …)), or leave its base atomic (\`flatten: false\`).`);
|
|
308
|
+
}
|
|
309
|
+
return {
|
|
310
|
+
...shape(...args),
|
|
311
|
+
"data-vx-src": src
|
|
312
|
+
};
|
|
313
|
+
};
|
|
314
|
+
const warned = /* @__PURE__ */ new Set();
|
|
315
|
+
/**
|
|
316
|
+
* Warns once per value that is neither a token (`variable`, the custom
|
|
317
|
+
* property it would read) nor a CSS value of `property`: the browser
|
|
318
|
+
* drops such a declaration without a word (PLAN D33).
|
|
319
|
+
*/
|
|
320
|
+
const check = (property, value, variable) => {
|
|
321
|
+
const { CSS, getComputedStyle, document } = globalThis;
|
|
322
|
+
const id = `${property}:${value}`;
|
|
323
|
+
if (!CSS?.supports || warned.has(id) || CSS.supports(property, value)) return;
|
|
324
|
+
if (variable && getComputedStyle && document && getComputedStyle(document.documentElement).getPropertyValue(variable) !== "") return;
|
|
325
|
+
warned.add(id);
|
|
326
|
+
console.warn(`vicss: \`${value}\` is ${variable ? "neither a token nor" : "not"} a valid value of \`${property}\`, so the browser ignores it. A function style writes a runtime value as it is${variable ? " when it names no token" : ""}: type the parameter Token<"…"> to name tokens, and pass a CSS value otherwise.`);
|
|
327
|
+
};
|
|
328
|
+
/** A function style's runtime value in dev: as in a build, checked. */
|
|
329
|
+
const devValue = (property, value) => {
|
|
330
|
+
if (typeof value == "string" && value) check(property, value);
|
|
331
|
+
return value;
|
|
332
|
+
};
|
|
333
|
+
/**
|
|
334
|
+
* A Token-typed parameter's value in dev: what core/compile.ts
|
|
335
|
+
* `tokenExpression` writes in a build, checked.
|
|
336
|
+
*/
|
|
337
|
+
const devToken = (property, prefix, value) => {
|
|
338
|
+
if (value == null) return void 0;
|
|
339
|
+
const text = String(value);
|
|
340
|
+
if (!/^[\w.-]+$/.test(text)) {
|
|
341
|
+
check(property, text);
|
|
342
|
+
return text;
|
|
343
|
+
}
|
|
344
|
+
const variable = prefix + text.replace(/\./g, "-");
|
|
345
|
+
check(property, text, variable);
|
|
346
|
+
return `var(${variable}, ${text})`;
|
|
347
|
+
};
|
|
348
|
+
/** React and Preact: `{ className, style, "data-vx-src" }`. */
|
|
349
|
+
const sxDev = /*#__PURE__*/ withSource(sx$1);
|
|
350
|
+
/** Solid and Vue: `{ class, style, "data-vx-src" }`, `style` an object. */
|
|
351
|
+
const sxDevClass = /*#__PURE__*/ withSource(sxClass);
|
|
352
|
+
/** Svelte, Astro and vanilla JS: `{ class, style, "data-vx-src" }`, `style` a string. */
|
|
353
|
+
const sxDevString = /*#__PURE__*/ withSource(sxString);
|
|
354
|
+
//#endregion
|
|
355
|
+
//#region src/index.ts
|
|
356
|
+
/**
|
|
357
|
+
* The runtime entry, `@menapo/vicss` (PLAN §5.1). In an app the plugin replaces
|
|
358
|
+
* `css()`, `recipe()`, `theme()`, `group()`, `peer()`, `keyframes()` and `token()`
|
|
359
|
+
* with constants, so only `sx` and the recipe resolver ship.
|
|
360
|
+
* Nothing here imports from the build side; the plugin lives in `/vite`.
|
|
361
|
+
*/
|
|
362
|
+
/**
|
|
363
|
+
* `sx()` with the public types: compiled styles and class strings in, the
|
|
364
|
+
* attributes of the project's framework out. The runtime's own signature
|
|
365
|
+
* returns React's shape.
|
|
366
|
+
*/
|
|
367
|
+
const sx = sx$1;
|
|
368
|
+
//#endregion
|
|
369
|
+
export { devToken as __vxDevToken, devValue as __vxDevValue, flatBases as __vxFlatBases, __vxRecipe, __vxResponsive, sxClass as __vxSxClass, sxDev as __vxSxDev, sxDevClass as __vxSxDevClass, sxDevString as __vxSxDevString, sxString as __vxSxString, css, group, keyframes, peer, recipe, sx, theme, token };
|
package/dist/lint.d.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
//#region src/lint/names.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The rules' names, apart from the analysis: the entry's declarations name
|
|
4
|
+
* them (`rules`), and the analysis imports Vite's AST types, which a project
|
|
5
|
+
* type-checking its lint config may not have installed.
|
|
6
|
+
*/
|
|
7
|
+
type RuleName = "static-styles" | "valid-styles" | "no-private-tokens" | "no-uncompiled-styles" | "no-arbitrary";
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/lint/rules.d.ts
|
|
10
|
+
/** A source range, as both linters' fixers take it. */
|
|
11
|
+
type Range = [number, number];
|
|
12
|
+
/** An edit, as a fixer makes it. */
|
|
13
|
+
interface Fix {
|
|
14
|
+
range: Range;
|
|
15
|
+
text: string;
|
|
16
|
+
}
|
|
17
|
+
/** The fixer both linters pass to `fix` and to a suggestion's `fix`. */
|
|
18
|
+
interface Fixer {
|
|
19
|
+
replaceTextRange(range: Range, text: string): Fix;
|
|
20
|
+
}
|
|
21
|
+
interface ReportBase {
|
|
22
|
+
readonly message: string;
|
|
23
|
+
readonly fix?: (fixer: Fixer) => Fix[];
|
|
24
|
+
readonly suggest?: Array<{
|
|
25
|
+
desc: string;
|
|
26
|
+
fix: (fixer: Fixer) => Fix[];
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
/** A report names a node (it has a `range` in both linters' ASTs) or a line and a column. */
|
|
30
|
+
type Report = ReportBase & ({
|
|
31
|
+
readonly node: {
|
|
32
|
+
readonly range: Range;
|
|
33
|
+
};
|
|
34
|
+
} | {
|
|
35
|
+
readonly loc: {
|
|
36
|
+
readonly line: number;
|
|
37
|
+
readonly column: number;
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
/** What a rule's `create` receives, in Oxlint and in ESLint: the part these rules read. */
|
|
41
|
+
interface RuleContext {
|
|
42
|
+
readonly filename: string;
|
|
43
|
+
readonly cwd?: string;
|
|
44
|
+
readonly options: readonly unknown[];
|
|
45
|
+
readonly settings?: Readonly<Record<string, unknown>>;
|
|
46
|
+
readonly sourceCode: {
|
|
47
|
+
readonly text: string;
|
|
48
|
+
readonly ast: unknown;
|
|
49
|
+
};
|
|
50
|
+
report(report: Report): void;
|
|
51
|
+
}
|
|
52
|
+
interface RuleMeta {
|
|
53
|
+
readonly type: "problem" | "suggestion";
|
|
54
|
+
readonly docs: {
|
|
55
|
+
readonly description: string;
|
|
56
|
+
readonly recommended: boolean;
|
|
57
|
+
readonly requiresSnapshot: boolean;
|
|
58
|
+
readonly url: string;
|
|
59
|
+
};
|
|
60
|
+
readonly fixable?: "code";
|
|
61
|
+
readonly hasSuggestions?: boolean;
|
|
62
|
+
/** JSON Schemas of the options, one per option. */
|
|
63
|
+
readonly schema: Array<Record<string, unknown>>;
|
|
64
|
+
}
|
|
65
|
+
interface Rule {
|
|
66
|
+
readonly meta: RuleMeta;
|
|
67
|
+
create(context: RuleContext): {
|
|
68
|
+
Program(node: unknown): void;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export declare const rules: Readonly<Record<RuleName, Rule>>;
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/lint/snapshot.d.ts
|
|
74
|
+
/** `settings.vicss` in the Oxlint or ESLint config. */
|
|
75
|
+
interface LintSettings {
|
|
76
|
+
/** The snapshot file, relative to the working directory, when it is not found by searching. */
|
|
77
|
+
readonly snapshot?: string;
|
|
78
|
+
/** Modules that re-export the vicss runtime, besides the config's `importSources`. */
|
|
79
|
+
readonly importSources?: readonly string[];
|
|
80
|
+
}
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/lint.d.ts
|
|
83
|
+
type Severity = "off" | "warn" | "error";
|
|
84
|
+
/** The rules `recommended` turns on: every rule but `no-arbitrary`, which a design-system team opts into. */
|
|
85
|
+
export declare const recommendedRules: Readonly<Record<string, Severity>>;
|
|
86
|
+
export interface VicssLintPlugin {
|
|
87
|
+
readonly meta: {
|
|
88
|
+
readonly name: "vicss";
|
|
89
|
+
};
|
|
90
|
+
readonly rules: Readonly<Record<string, Rule>>;
|
|
91
|
+
readonly configs: {
|
|
92
|
+
/** An ESLint flat config object; its `rules` serve Oxlint's config too. */
|
|
93
|
+
readonly recommended: {
|
|
94
|
+
readonly name: string;
|
|
95
|
+
readonly plugins: {
|
|
96
|
+
readonly vicss: VicssLintPlugin;
|
|
97
|
+
};
|
|
98
|
+
readonly rules: Readonly<Record<string, Severity>>;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
declare const plugin: VicssLintPlugin;
|
|
103
|
+
export declare const configs: {
|
|
104
|
+
/** An ESLint flat config object; its `rules` serve Oxlint's config too. */
|
|
105
|
+
readonly recommended: {
|
|
106
|
+
readonly name: string;
|
|
107
|
+
readonly plugins: {
|
|
108
|
+
readonly vicss: VicssLintPlugin;
|
|
109
|
+
};
|
|
110
|
+
readonly rules: Readonly<Record<string, Severity>>;
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
//#endregion
|
|
114
|
+
export { type Fix, type Fixer, type LintSettings, type Range, type Report, type Rule, type RuleContext, type RuleMeta, plugin as default };
|
package/dist/lint.js
ADDED
|
Binary file
|