rainbowindex 0.5.0 → 0.6.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/CHANGELOG.md +530 -0
- package/README.md +70 -39
- package/dist/browser.d.ts +2 -2
- package/dist/browser.mjs +1 -3
- package/dist/{chunk-CMB6BHVE.mjs → chunk-3LWJTLOJ.mjs} +62 -38
- package/dist/{chunk-KRZL4IDK.mjs → chunk-6U4IOFOS.mjs} +687 -859
- package/dist/{chunk-ZI5ZYNSU.mjs → chunk-KSNYSR3C.mjs} +5629 -5092
- package/dist/{chunk-DT5HYIM3.mjs → chunk-WK6S4HTC.mjs} +978 -901
- package/dist/{chunk-NXJZX6KI.mjs → chunk-ZR7XJMUN.mjs} +15 -8
- package/dist/cli.mjs +34 -11
- package/dist/editor.d.ts +35 -9
- package/dist/editor.mjs +34 -8
- package/dist/{index-Dp6i5TSv.d.ts → index-4Kyaq3IZ.d.ts} +29 -6
- package/dist/{context-ruu2x_jR.d.ts → index-DSgpB6bS.d.ts} +90 -69
- package/dist/index.d.ts +7 -4
- package/dist/index.mjs +14 -9
- package/dist/oxlint.d.ts +55 -0
- package/dist/oxlint.mjs +38 -0
- package/dist/{safelist-D9-Plqta.d.ts → safelist-CGCtF-Fr.d.ts} +2 -15
- package/dist/vite.mjs +67 -14
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -20,6 +20,8 @@ The product is not a visual design tool, a component library, or a framework abs
|
|
|
20
20
|
|
|
21
21
|
When tradeoffs arise, we consistently prioritize composability, user control, predictable performance, explicit behavior, and correctness over convenience or familiarity.
|
|
22
22
|
|
|
23
|
+
Full consumer documentation lives in [docs/](docs/README.md).
|
|
24
|
+
|
|
23
25
|
## Install
|
|
24
26
|
|
|
25
27
|
```sh
|
|
@@ -67,15 +69,21 @@ export default defineConfig({
|
|
|
67
69
|
```css
|
|
68
70
|
/* src/styles.css */
|
|
69
71
|
@import "rainbowindex";
|
|
72
|
+
|
|
73
|
+
@color {
|
|
74
|
+
brand: 0.18 330;
|
|
75
|
+
}
|
|
70
76
|
```
|
|
71
77
|
|
|
72
78
|
```tsx
|
|
73
79
|
// src/App.tsx
|
|
74
80
|
export default function App() {
|
|
75
|
-
return <div className="flex gap-4 px-6 py-3 bg-
|
|
81
|
+
return <div className="flex gap-4 px-6 py-3 bg-brand-500 text-white">Hello</div>;
|
|
76
82
|
}
|
|
77
83
|
```
|
|
78
84
|
|
|
85
|
+
The default palette ships only the neutral `theme` color (plus `black`, `white`, `paper`, `ink`, `transparent`, `current`, `inherit`) — declare your palette with `@color`.
|
|
86
|
+
|
|
79
87
|
To scaffold a fresh app instead, use the CLI:
|
|
80
88
|
|
|
81
89
|
```sh
|
|
@@ -86,14 +94,15 @@ pnpm dlx rainbowindex init
|
|
|
86
94
|
|
|
87
95
|
## CLI
|
|
88
96
|
|
|
89
|
-
The `rainbowindex` binary exposes
|
|
97
|
+
The `rainbowindex` binary exposes six subcommands. The default is `build`.
|
|
90
98
|
|
|
91
99
|
```
|
|
92
100
|
rainbowindex <glob> [options] Generate CSS from source files
|
|
93
101
|
rainbowindex init Wire Rainbow Index into the current Vite app
|
|
94
102
|
rainbowindex create <dir> Scaffold a Vite app with Rainbow Index ready
|
|
95
103
|
rainbowindex generate-types Generate TypeScript types for ri() autocomplete
|
|
96
|
-
rainbowindex preload-fonts
|
|
104
|
+
rainbowindex preload-fonts Print <link rel="preload"> tags for local faces marked preload
|
|
105
|
+
rainbowindex scan <glob> Print the class names the scanner extracts from files
|
|
97
106
|
```
|
|
98
107
|
|
|
99
108
|
Common flags:
|
|
@@ -103,7 +112,7 @@ Common flags:
|
|
|
103
112
|
| `-o`, `--output <file>` | Output CSS file path. Required with `--watch`. |
|
|
104
113
|
| `--watch` | Re-run on source-file changes (chokidar). |
|
|
105
114
|
| `--minify` | Minification + browser-fallback passes via LightningCSS. `--optimize` is an accepted alias. |
|
|
106
|
-
| `--css <file>` | CSS input with directives. Auto-detected if omitted. |
|
|
115
|
+
| `--css <file>` | CSS input with directives. Auto-detected if omitted. For `init`/`create`: the stylesheet to create or patch (default `src/index.css`). |
|
|
107
116
|
| `--strict` | Drop the string escape hatch in generated types. |
|
|
108
117
|
| `--template <name>` | Vite template to scaffold (default: `react-ts`). |
|
|
109
118
|
|
|
@@ -130,7 +139,7 @@ Options:
|
|
|
130
139
|
|
|
131
140
|
| Option | Type | Description |
|
|
132
141
|
| --- | --- | --- |
|
|
133
|
-
| `sources` | `string[]` | Glob patterns for files to scan. Can also be declared via `@source` in CSS. |
|
|
142
|
+
| `sources` | `string[]` | Glob patterns for files to scan. Can also be declared via `@source` in CSS. Any positive glob (here or via `@source`) replaces the default scan patterns. |
|
|
134
143
|
| `cwd` | `string` | Working directory. Defaults to `process.cwd()`. |
|
|
135
144
|
|
|
136
145
|
## Vite plugin
|
|
@@ -139,7 +148,25 @@ Options:
|
|
|
139
148
|
import rainbowindex from "rainbowindex/vite";
|
|
140
149
|
```
|
|
141
150
|
|
|
142
|
-
Auto-detects your CSS entry, injects a PostCSS config if none exists, supports HMR with file versioning.
|
|
151
|
+
Auto-detects your CSS entry, injects a PostCSS config if none exists, supports HMR with file versioning. The plugin takes no options — to pass PostCSS options, create a `postcss.config.js` and register the PostCSS plugin there yourself.
|
|
152
|
+
|
|
153
|
+
## Vite+
|
|
154
|
+
|
|
155
|
+
[Vite+](https://viteplus.dev) works out of the box. Directive syntax is not valid CSS, so Oxfmt — the formatter behind `vp fmt` and `vp check` — cannot parse a stylesheet that holds directives, and the whole check fails before it lints or type checks. The Vite plugin prevents that: it adds every activated stylesheet to `fmt.ignorePatterns`, and leaves the rest of the project formatted. Without the Vite plugin, add the pattern yourself.
|
|
156
|
+
|
|
157
|
+
One more integration is opt-in:
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
// vite.config.ts — lint rule: merge classes with ri(), not clsx/tailwind-merge
|
|
161
|
+
export default defineConfig({
|
|
162
|
+
lint: {
|
|
163
|
+
jsPlugins: [{ name: "rainbowindex", specifier: "rainbowindex/oxlint" }],
|
|
164
|
+
rules: { "rainbowindex/prefer-ri": "error" },
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
See [docs/vite-plus.md](docs/vite-plus.md).
|
|
143
170
|
|
|
144
171
|
## Class syntax
|
|
145
172
|
|
|
@@ -152,7 +179,7 @@ Roughly the same surface area as Tailwind: spacing, sizing, typography, color, l
|
|
|
152
179
|
Prefix any utility with one or more variants, separated by `:`.
|
|
153
180
|
|
|
154
181
|
```html
|
|
155
|
-
<button class="bg-
|
|
182
|
+
<button class="bg-brand-500 hover:bg-brand-600 dark:bg-brand-400 sm:px-6">…</button>
|
|
156
183
|
```
|
|
157
184
|
|
|
158
185
|
Supported variants:
|
|
@@ -160,11 +187,13 @@ Supported variants:
|
|
|
160
187
|
- **Pseudo-classes** — `hover`, `focus`, `focus-visible`, `active`, `visited`, `disabled`, `enabled`, `checked`, `empty`, `first`, `last`, `odd`, `even`, `only`
|
|
161
188
|
- **Pseudo-elements** — `before`, `after`, `placeholder`, `file`, `marker`, `selection`, `first-line`, `first-letter`, `backdrop`
|
|
162
189
|
- **Media** — `dark`, `print`, `portrait`, `landscape`, `motion-safe`, `motion-reduce`, `starting`
|
|
163
|
-
- **Breakpoints** —
|
|
164
|
-
- **Container queries** —
|
|
190
|
+
- **Breakpoints** — every name from `@breakpoint`; none ships
|
|
191
|
+
- **Container queries** — the same names with an `@` prefix
|
|
165
192
|
- **Attribute selectors** — `data-[state=open]`, `aria-[pressed=true]`
|
|
166
193
|
- **Arbitrary** — `[selector]`, `[@media(...)]`
|
|
167
194
|
|
|
195
|
+
This list is a subset — the full variant tables are in [docs/class-syntax.md](docs/class-syntax.md).
|
|
196
|
+
|
|
168
197
|
### Arbitrary values
|
|
169
198
|
|
|
170
199
|
```html
|
|
@@ -183,24 +212,21 @@ When multiple utilities share the same variant prefix, group them with `{…}` i
|
|
|
183
212
|
|
|
184
213
|
```html
|
|
185
214
|
<!-- These two lines are equivalent -->
|
|
186
|
-
<div class="hover:text-
|
|
187
|
-
<div class="hover:{text-
|
|
215
|
+
<div class="hover:text-brand-500 hover:bg-brand-100 hover:underline">…</div>
|
|
216
|
+
<div class="hover:{text-brand-500 bg-brand-100 underline}">…</div>
|
|
188
217
|
```
|
|
189
218
|
|
|
190
|
-
|
|
219
|
+
Prefixes chain:
|
|
191
220
|
|
|
192
221
|
```html
|
|
193
222
|
<!-- Chained variants -->
|
|
194
|
-
<div class="sm:hover:{bg-
|
|
223
|
+
<div class="sm:hover:{bg-theme-700 text-white}">…</div>
|
|
195
224
|
|
|
196
225
|
<!-- Multiple groups in one class string -->
|
|
197
|
-
<div class="focus:{outline-2 outline-
|
|
198
|
-
|
|
199
|
-
<!-- The data-attribute case -->
|
|
200
|
-
<div class="data-[active]:{relative px-2} data-[slot=sidebar]:{fixed leading-none}">…</div>
|
|
226
|
+
<div class="focus:{outline-2 outline-brand-500} disabled:{opacity-50 cursor-not-allowed}">…</div>
|
|
201
227
|
```
|
|
202
228
|
|
|
203
|
-
Expansion happens at scan-time, so the runtime never sees the grouped form.
|
|
229
|
+
Expansion happens at scan-time, so the runtime never sees the grouped form. Only plain prefixes work — bracketed variants like `data-[state=open]:` cannot prefix a group, and braces do not nest (chain the prefixes instead). Expansion input is capped at 500,000 characters, output at 100,000.
|
|
204
230
|
|
|
205
231
|
## Theming with CSS directives
|
|
206
232
|
|
|
@@ -211,8 +237,8 @@ Customization happens in your CSS input, not a JS config. The engine recognizes:
|
|
|
211
237
|
| `@color` | Define color tokens. Supports generative (`chroma hue`), explicit (`oklch(...)`, `#rrggbb`), light/dark pairs, and aliases. |
|
|
212
238
|
| `@spacing` | Set the spacing base unit. |
|
|
213
239
|
| `@text` | Define text size tokens (`size, line-height`). |
|
|
214
|
-
| `@font
|
|
215
|
-
| `@rounded` |
|
|
240
|
+
| `@font` | Register font families inside a single `@font { … }` block. Local files are repeatable `face:` entries (e.g. upright + italic). Known families get an automatic zero-CLS metrics fallback (`metrics: none` opts out). Plain `@font-face` rules are standard CSS and pass through untouched. |
|
|
241
|
+
| `@rounded` | Corner shape (`round`, `squircle`, `superellipse(N)`, etc), and named radii. Unnamed radii are spacing multiples: `rounded-4`. |
|
|
216
242
|
| `@fluid` | Configure fluid type/spacing range. |
|
|
217
243
|
| `@animate` | Register named animations with inline `@keyframes`. |
|
|
218
244
|
| `@utility` | Define a custom utility (static or functional `name-*`). |
|
|
@@ -221,7 +247,12 @@ Customization happens in your CSS input, not a JS config. The engine recognizes:
|
|
|
221
247
|
| `@slot` | Slot marker inside `@custom` block form. |
|
|
222
248
|
| `@source` | Declare additional source globs from CSS. Supports `not "..."` and `inline("...")`. |
|
|
223
249
|
| `@preflight` | Toggle preflight base styles. |
|
|
224
|
-
| `@
|
|
250
|
+
| `@breakpoint`, `@shadow`, `@weight`, `@ease`, `@blur`, `@z`, `@leading`, `@tracking`, `@opacity`, `@duration` | Key-value token scales; `!key;` removes a token. |
|
|
251
|
+
| `@register` | Emit CSS `@property` registrations. |
|
|
252
|
+
| `@layer` | Place the generated output in cascade layers (intercepted, own grammar). |
|
|
253
|
+
| `@media`, `@import`, other standard at-rules | Standard CSS — passed through untouched. |
|
|
254
|
+
|
|
255
|
+
A named scale can also hold utilities. A `name { … }` block with no colon before it defines a utility in that scale's class family, so `@shadow { lifted-* { … } }` makes `shadow-lifted-*`. See [theming.md](docs/theming.md#utility-blocks).
|
|
225
256
|
|
|
226
257
|
Example:
|
|
227
258
|
|
|
@@ -250,11 +281,11 @@ Example:
|
|
|
250
281
|
}
|
|
251
282
|
}
|
|
252
283
|
|
|
253
|
-
@source "
|
|
254
|
-
@source not "
|
|
284
|
+
@source "emails/**/*.html";
|
|
285
|
+
@source not "src/**/legacy/*";
|
|
255
286
|
```
|
|
256
287
|
|
|
257
|
-
|
|
288
|
+
The package ships two defaults: the `colors` palette and the `spacing` base. Every other scale — `text`, `leading`, `tracking`, `shadows`, `radii`, `breakpoints`, `weights`, `easing`, `blur`, `animations`, `fluid`, `z`, `opacity`, `duration` — starts empty, and its directive defines the named tokens. Numeric and keyword class forms are computed, so they work with no theme at all.
|
|
258
289
|
|
|
259
290
|
## `ri()` — runtime class merger
|
|
260
291
|
|
|
@@ -263,8 +294,8 @@ Default theme keys: `colors`, `spacing`, `text`, `breakpoints`, `rounded`, `shad
|
|
|
263
294
|
```ts
|
|
264
295
|
import { ri } from "rainbowindex";
|
|
265
296
|
|
|
266
|
-
ri("px-2 py-1", isActive && "bg-
|
|
267
|
-
// → "py-1 bg-
|
|
297
|
+
ri("px-2 py-1", isActive && "bg-brand-500", "px-4");
|
|
298
|
+
// → "py-1 bg-brand-500 px-4" (px-2 is dropped — px-4 wins)
|
|
268
299
|
```
|
|
269
300
|
|
|
270
301
|
Accepted inputs:
|
|
@@ -297,17 +328,17 @@ themes in the same Node process, that shared state will leak — use
|
|
|
297
328
|
// Anywhere ri() is single-compile-safe (browser, Vite, PostCSS):
|
|
298
329
|
import { ri } from "rainbowindex";
|
|
299
330
|
|
|
300
|
-
const className = ri("px-2 py-1", isActive && "bg-
|
|
331
|
+
const className = ri("px-2 py-1", isActive && "bg-brand-500", "px-4");
|
|
301
332
|
```
|
|
302
333
|
|
|
303
334
|
```ts
|
|
304
|
-
// SSR / multi-tenant —
|
|
305
|
-
import { compileProject, createRi
|
|
335
|
+
// SSR / multi-tenant — bind a merger to one compile, isolated per theme:
|
|
336
|
+
import { compileProject, createRi } from "rainbowindex";
|
|
337
|
+
import { createThemeSnapshot } from "rainbowindex/editor";
|
|
306
338
|
|
|
307
339
|
// At server startup (once per theme):
|
|
308
|
-
const
|
|
309
|
-
const
|
|
310
|
-
const ri = createRi(snapshot);
|
|
340
|
+
const result = await compileProject({ css });
|
|
341
|
+
const ri = createRi(createThemeSnapshot(result.theme));
|
|
311
342
|
|
|
312
343
|
// In your request handler:
|
|
313
344
|
function render(req, res) {
|
|
@@ -316,9 +347,9 @@ function render(req, res) {
|
|
|
316
347
|
}
|
|
317
348
|
```
|
|
318
349
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
350
|
+
In any Node/SSR process, the default `ri()` emits a throttled `[RI-2004]`
|
|
351
|
+
warning (at most once per 60 s) to flag its shared module state. Switching to
|
|
352
|
+
`createRi(snapshot)` silences it.
|
|
322
353
|
|
|
323
354
|
## Editor tooling API
|
|
324
355
|
|
|
@@ -370,16 +401,16 @@ Warnings carry `RI-NNNN` codes. Ranges:
|
|
|
370
401
|
|
|
371
402
|
| Range | Subsystem |
|
|
372
403
|
| --- | --- |
|
|
404
|
+
| 00xx | PostCSS plugin bootstrap (thrown) |
|
|
373
405
|
| 10xx | Compilation & directives |
|
|
374
|
-
| 11xx | Color directives |
|
|
406
|
+
| 11xx | Color directives & resolver catch-alls |
|
|
375
407
|
| 12xx | Font system |
|
|
376
408
|
| 13xx | Merge / compilation context |
|
|
377
409
|
| 14xx | Source scanner |
|
|
378
410
|
| 15xx | Typography utilities |
|
|
379
411
|
| 16xx | Integration plugins (Vite, PostCSS, CLI wiring) |
|
|
380
|
-
| 20xx | CSS
|
|
381
|
-
| 21xx | `ri()` runtime |
|
|
412
|
+
| 20xx | CSS functions, `ri()` runtime & `compile()` validation |
|
|
382
413
|
|
|
383
|
-
See
|
|
414
|
+
See [docs/diagnostics.md](docs/diagnostics.md) for the full code → cause → fix table.
|
|
384
415
|
|
|
385
416
|
Warnings are deduplicated and capped at 200 per compile, with 20 slots reserved for high-severity errors.
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { C as ColorDefinition, a as CompilationContext, b as CompilationSnapshot, F as FluidConfig, T as TextSize, c as Theme, d as createCompilationContext, e as defaultTheme, f as finalizeCompilationContext, r as registerColorNames, g as registerCustomFontFamilies, h as registerCustomTextSizes, i as registerCustomUtility } from './
|
|
2
|
-
export {
|
|
1
|
+
export { C as ColorDefinition, a as CompilationContext, b as CompilationSnapshot, F as FluidConfig, T as TextSize, c as Theme, d as createCompilationContext, e as defaultTheme, f as finalizeCompilationContext, r as registerColorNames, g as registerCustomFontFamilies, h as registerCustomTextSizes, i as registerCustomUtility } from './index-DSgpB6bS.js';
|
|
2
|
+
export { c as createRi, r as ri, s as safelist } from './safelist-CGCtF-Fr.js';
|
|
3
3
|
|
|
4
4
|
declare function browserEntryUnavailable(): never;
|
|
5
5
|
|
package/dist/browser.mjs
CHANGED
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
safelist
|
|
3
3
|
} from "./chunk-PD4ZXGJ6.mjs";
|
|
4
4
|
import {
|
|
5
|
-
DEFAULT_TEXT_SIZES,
|
|
6
5
|
createCompilationContext,
|
|
7
6
|
createRi,
|
|
8
7
|
defaultTheme,
|
|
@@ -13,7 +12,7 @@ import {
|
|
|
13
12
|
registerCustomTextSizes,
|
|
14
13
|
registerCustomUtility,
|
|
15
14
|
ri
|
|
16
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-6U4IOFOS.mjs";
|
|
17
16
|
|
|
18
17
|
// src/entries/browser.ts
|
|
19
18
|
function browserEntryUnavailable() {
|
|
@@ -26,7 +25,6 @@ function browserEntryUnavailable() {
|
|
|
26
25
|
}
|
|
27
26
|
var browser_default = browserEntryUnavailable;
|
|
28
27
|
export {
|
|
29
|
-
DEFAULT_TEXT_SIZES,
|
|
30
28
|
createCompilationContext,
|
|
31
29
|
createRi,
|
|
32
30
|
browser_default as default,
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
2
|
compileScannedProject
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WK6S4HTC.mjs";
|
|
4
4
|
import {
|
|
5
5
|
APPLY_ALIASES,
|
|
6
6
|
DIRECTIVE_NAMES_SET,
|
|
7
7
|
MAX_DIRECTIVE_INPUT_SIZE,
|
|
8
8
|
RI_IMPORT_SPECIFIER_ALTERNATION,
|
|
9
9
|
applyVariantWrappers,
|
|
10
|
+
checkAppliedFontWeights,
|
|
10
11
|
compileCSSFunctions,
|
|
11
12
|
computeSortKey,
|
|
12
13
|
expandVariantGroups,
|
|
13
|
-
|
|
14
|
-
getCustomUtility,
|
|
14
|
+
forEachApplyClassList,
|
|
15
15
|
hasApplyLikeDirective,
|
|
16
16
|
hasCSSFunctions,
|
|
17
17
|
hasRIActivation,
|
|
18
|
+
matchCustomUtility,
|
|
18
19
|
parseUtility,
|
|
19
20
|
pushWarningsDeduped,
|
|
20
21
|
resolveUtilityDeclarations,
|
|
21
22
|
resolveVariant,
|
|
22
23
|
splitSelectorList
|
|
23
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-KSNYSR3C.mjs";
|
|
24
25
|
|
|
25
26
|
// src/integrations/postcss/index.ts
|
|
26
27
|
import postcss2 from "postcss";
|
|
@@ -28,6 +29,7 @@ import { isAbsolute } from "path";
|
|
|
28
29
|
|
|
29
30
|
// src/integrations/postcss/apply.ts
|
|
30
31
|
import postcss from "postcss";
|
|
32
|
+
var applyStateByTheme = /* @__PURE__ */ new WeakMap();
|
|
31
33
|
function makeDeclGroup(r) {
|
|
32
34
|
const sortKey = computeSortKey(r.declarations[0]?.property ?? "");
|
|
33
35
|
return {
|
|
@@ -94,22 +96,29 @@ function resolveFullNestingSelector(rule) {
|
|
|
94
96
|
}
|
|
95
97
|
return composeNestedSelectors(parts);
|
|
96
98
|
}
|
|
97
|
-
function processApply(root, theme, warnings) {
|
|
99
|
+
function processApply(root, theme, warnings, cssPath) {
|
|
98
100
|
for (const alias of APPLY_ALIASES) {
|
|
99
101
|
root.walkAtRules(alias, (atRule) => {
|
|
100
102
|
atRule.name = "apply";
|
|
101
103
|
});
|
|
102
104
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
let state = applyStateByTheme.get(theme);
|
|
106
|
+
if (!state) {
|
|
107
|
+
state = {
|
|
108
|
+
customVariantMap: new Map(theme.customVariants.map((cv) => [cv.name, cv])),
|
|
109
|
+
applyRootWarnings: /* @__PURE__ */ new Map(),
|
|
110
|
+
resolveCache: /* @__PURE__ */ new Map()
|
|
111
|
+
};
|
|
112
|
+
applyStateByTheme.set(theme, state);
|
|
113
|
+
}
|
|
114
|
+
const { customVariantMap, applyRootWarnings, resolveCache } = state;
|
|
106
115
|
for (let depth = 0; depth < MAX_APPLY_DEPTH; depth++) {
|
|
107
116
|
const applyNodes = [];
|
|
108
117
|
const classListByNode = /* @__PURE__ */ new Map();
|
|
109
118
|
const groupRoots = /* @__PURE__ */ new Set();
|
|
110
119
|
root.walkAtRules("apply", (atRule) => {
|
|
111
120
|
applyNodes.push(atRule);
|
|
112
|
-
const params = expandVariantGroups(atRule.params, warnings);
|
|
121
|
+
const params = expandVariantGroups(atRule.params, warnings, cssPath);
|
|
113
122
|
const classNames = params.trim().split(/\s+/).filter(Boolean);
|
|
114
123
|
classListByNode.set(atRule, classNames);
|
|
115
124
|
if (classNames.includes("group")) {
|
|
@@ -128,7 +137,7 @@ function processApply(root, theme, warnings) {
|
|
|
128
137
|
warnings,
|
|
129
138
|
customVariantMap,
|
|
130
139
|
groupRoots,
|
|
131
|
-
|
|
140
|
+
applyRootWarnings,
|
|
132
141
|
resolveCache
|
|
133
142
|
);
|
|
134
143
|
}
|
|
@@ -146,7 +155,7 @@ function processApply(root, theme, warnings) {
|
|
|
146
155
|
}
|
|
147
156
|
}
|
|
148
157
|
}
|
|
149
|
-
function expandApply(atRule, classNames, theme, warnings, customVariantMap, groupRoots,
|
|
158
|
+
function expandApply(atRule, classNames, theme, warnings, customVariantMap, groupRoots, applyRootWarnings, resolveCache) {
|
|
150
159
|
const parentRule = atRule.parent;
|
|
151
160
|
if (parentRule?.type !== "rule") {
|
|
152
161
|
warnings.push("[RI-1006] @apply must be used inside a CSS rule, not at the top level.");
|
|
@@ -166,6 +175,7 @@ function expandApply(atRule, classNames, theme, warnings, customVariantMap, grou
|
|
|
166
175
|
atRule.remove();
|
|
167
176
|
return;
|
|
168
177
|
}
|
|
178
|
+
checkAppliedFontWeights(classNames, theme, warnings);
|
|
169
179
|
const resolved = [];
|
|
170
180
|
for (const className of classNames) {
|
|
171
181
|
let entry = resolveCache.get(className);
|
|
@@ -177,7 +187,7 @@ function expandApply(atRule, classNames, theme, warnings, customVariantMap, grou
|
|
|
177
187
|
theme,
|
|
178
188
|
entryWarnings,
|
|
179
189
|
customVariantMap,
|
|
180
|
-
|
|
190
|
+
applyRootWarnings
|
|
181
191
|
),
|
|
182
192
|
warnings: entryWarnings
|
|
183
193
|
};
|
|
@@ -252,19 +262,24 @@ function expandApply(atRule, classNames, theme, warnings, customVariantMap, grou
|
|
|
252
262
|
parentContainer.insertAfter(insertAfter, rule);
|
|
253
263
|
insertAfter = rule;
|
|
254
264
|
}
|
|
255
|
-
const groupInfoByKey = /* @__PURE__ */ new Map();
|
|
256
|
-
let hasGroupVariants = false;
|
|
257
|
-
for (const [key, bucket] of variantBuckets) {
|
|
258
|
-
const info = resolveGroupVariantInfo(bucket.wrappers, parentRule, groupRoots);
|
|
259
|
-
groupInfoByKey.set(key, info);
|
|
260
|
-
if (info) hasGroupVariants = true;
|
|
261
|
-
}
|
|
262
265
|
let fullSelectorMemo = null;
|
|
263
266
|
const fullNestingSelector = () => {
|
|
264
267
|
if (fullSelectorMemo === null)
|
|
265
268
|
fullSelectorMemo = resolveFullNestingSelector(parentRule);
|
|
266
269
|
return fullSelectorMemo;
|
|
267
270
|
};
|
|
271
|
+
const groupInfoByKey = /* @__PURE__ */ new Map();
|
|
272
|
+
let hasGroupVariants = false;
|
|
273
|
+
for (const [key, bucket] of variantBuckets) {
|
|
274
|
+
const info = resolveGroupVariantInfo(
|
|
275
|
+
bucket.wrappers,
|
|
276
|
+
parentRule,
|
|
277
|
+
groupRoots,
|
|
278
|
+
fullNestingSelector
|
|
279
|
+
);
|
|
280
|
+
groupInfoByKey.set(key, info);
|
|
281
|
+
if (info) hasGroupVariants = true;
|
|
282
|
+
}
|
|
268
283
|
let docRootMemo = null;
|
|
269
284
|
const docRoot = () => {
|
|
270
285
|
if (docRootMemo === null) docRootMemo = parentContainer.root();
|
|
@@ -276,7 +291,7 @@ function expandApply(atRule, classNames, theme, warnings, customVariantMap, grou
|
|
|
276
291
|
if (groupVariantInfo) {
|
|
277
292
|
const fullSelector = fullNestingSelector();
|
|
278
293
|
const { groupRootSelector } = groupVariantInfo;
|
|
279
|
-
const rootBranches = splitSelectorList(groupRootSelector);
|
|
294
|
+
const rootBranches = groupVariantInfo.isSelf ? [] : splitSelectorList(groupRootSelector);
|
|
280
295
|
const fullBranches = splitSelectorList(fullSelector);
|
|
281
296
|
const baseBranches = [];
|
|
282
297
|
for (const fb of fullBranches) {
|
|
@@ -332,7 +347,7 @@ function expandApply(atRule, classNames, theme, warnings, customVariantMap, grou
|
|
|
332
347
|
}
|
|
333
348
|
atRule.remove();
|
|
334
349
|
}
|
|
335
|
-
function resolveGroupVariantInfo(wrappers, parentRule, groupRoots) {
|
|
350
|
+
function resolveGroupVariantInfo(wrappers, parentRule, groupRoots, fullNestingSelector) {
|
|
336
351
|
if (groupRoots.size === 0) return null;
|
|
337
352
|
const hasGroupVariant = wrappers.some(
|
|
338
353
|
(w) => w.selectorSuffix && w.replaceAmpersand && GROUP_VARIANT_RE.test(w.selectorSuffix)
|
|
@@ -340,28 +355,31 @@ function resolveGroupVariantInfo(wrappers, parentRule, groupRoots) {
|
|
|
340
355
|
if (!hasGroupVariant) return null;
|
|
341
356
|
const groupInfo = findGroupAncestor(parentRule, groupRoots);
|
|
342
357
|
if (!groupInfo) return null;
|
|
358
|
+
const isSelf = fullNestingSelector() === groupInfo.groupRootSelector;
|
|
343
359
|
const rewrittenWrappers = wrappers.map((w) => {
|
|
344
360
|
if (!w.selectorSuffix || !w.replaceAmpersand) return w;
|
|
345
361
|
const match = w.selectorSuffix.match(GROUP_VARIANT_RE);
|
|
346
362
|
if (!match) return w;
|
|
347
363
|
const pseudo = match[1];
|
|
364
|
+
if (isSelf) return { ...w, selectorSuffix: `&${pseudo}` };
|
|
348
365
|
const rootBranches = splitSelectorList(groupInfo.groupRootSelector);
|
|
349
366
|
const newSuffix = rootBranches.map((b) => `${b}${pseudo} &`).join(", ");
|
|
350
367
|
return { ...w, selectorSuffix: newSuffix };
|
|
351
368
|
});
|
|
352
|
-
return { rewrittenWrappers, groupRootSelector: groupInfo.groupRootSelector };
|
|
369
|
+
return { rewrittenWrappers, groupRootSelector: groupInfo.groupRootSelector, isSelf };
|
|
353
370
|
}
|
|
354
371
|
var MARKER_CLASSES = /* @__PURE__ */ new Set(["group"]);
|
|
355
372
|
var MAX_CUSTOM_APPLY_DEPTH = 5;
|
|
356
|
-
function findCustomUtility(utility, value, theme) {
|
|
357
|
-
|
|
358
|
-
const cu = getCustomUtility(theme, target);
|
|
359
|
-
return cu && !cu.functional ? cu : void 0;
|
|
373
|
+
function findCustomUtility(utility, value, negative, theme) {
|
|
374
|
+
return matchCustomUtility(utility, value, negative, theme)?.cu;
|
|
360
375
|
}
|
|
361
376
|
function checkCustomApplyWarnings(cu, theme, warnings, visiting = /* @__PURE__ */ new Set()) {
|
|
362
377
|
if (!hasApplyLikeDirective(cu.body)) return;
|
|
363
378
|
const innerClasses = [];
|
|
364
|
-
|
|
379
|
+
forEachApplyClassList(cu.body, (classes) => {
|
|
380
|
+
checkAppliedFontWeights(classes, theme, warnings);
|
|
381
|
+
innerClasses.push(...classes);
|
|
382
|
+
});
|
|
365
383
|
if (innerClasses.length === 0) return;
|
|
366
384
|
if (visiting.has(cu.name)) {
|
|
367
385
|
warnings.push(
|
|
@@ -378,12 +396,12 @@ function checkCustomApplyWarnings(cu, theme, warnings, visiting = /* @__PURE__ *
|
|
|
378
396
|
visiting.add(cu.name);
|
|
379
397
|
for (const innerClass of innerClasses) {
|
|
380
398
|
const parsed = parseUtility(innerClass);
|
|
381
|
-
const innerCu = findCustomUtility(parsed.utility, parsed.value, theme);
|
|
399
|
+
const innerCu = findCustomUtility(parsed.utility, parsed.value, parsed.negative, theme);
|
|
382
400
|
if (innerCu) checkCustomApplyWarnings(innerCu, theme, warnings, visiting);
|
|
383
401
|
}
|
|
384
402
|
visiting.delete(cu.name);
|
|
385
403
|
}
|
|
386
|
-
function resolveClassName(className, theme, warnings, customVariantMap,
|
|
404
|
+
function resolveClassName(className, theme, warnings, customVariantMap, applyRootWarnings) {
|
|
387
405
|
const parsed = parseUtility(className);
|
|
388
406
|
if (parsed.variants.length === 0 && MARKER_CLASSES.has(parsed.utility) && parsed.value === null) {
|
|
389
407
|
return null;
|
|
@@ -394,10 +412,15 @@ function resolveClassName(className, theme, warnings, customVariantMap, checkedA
|
|
|
394
412
|
return null;
|
|
395
413
|
}
|
|
396
414
|
const declarations = [...utilResult.declarations];
|
|
397
|
-
const cu = findCustomUtility(parsed.utility, parsed.value, theme);
|
|
398
|
-
if (cu
|
|
399
|
-
|
|
400
|
-
|
|
415
|
+
const cu = findCustomUtility(parsed.utility, parsed.value, parsed.negative, theme);
|
|
416
|
+
if (cu) {
|
|
417
|
+
let cuWarnings = applyRootWarnings.get(cu.name);
|
|
418
|
+
if (!cuWarnings) {
|
|
419
|
+
cuWarnings = [];
|
|
420
|
+
checkCustomApplyWarnings(cu, theme, cuWarnings);
|
|
421
|
+
applyRootWarnings.set(cu.name, cuWarnings);
|
|
422
|
+
}
|
|
423
|
+
warnings.push(...cuWarnings);
|
|
401
424
|
}
|
|
402
425
|
const variantWrappers = [];
|
|
403
426
|
for (const variant of parsed.variants) {
|
|
@@ -564,28 +587,29 @@ var rainbowindex = (options = {}) => {
|
|
|
564
587
|
if (!hasActivation) {
|
|
565
588
|
return;
|
|
566
589
|
}
|
|
590
|
+
const from = root.source?.input?.file ?? root.source?.input?.id ?? root.source?.input?.from ?? "<rainbowindex>";
|
|
567
591
|
const { compiled, warningSeen } = await compileScannedProject({
|
|
568
592
|
css: rawCSS,
|
|
569
593
|
cwd,
|
|
594
|
+
cssPath: from,
|
|
570
595
|
surfacePatterns: options.sources,
|
|
571
596
|
onInvalidPattern: (err) => `[RI-1015] ${err}`
|
|
572
597
|
});
|
|
573
598
|
const compilationWarnings = compiled.warnings;
|
|
574
|
-
const from = root.source?.input?.file ?? root.source?.input?.id ?? root.source?.input?.from ?? "<rainbowindex>";
|
|
575
599
|
stripRIDirectiveNodes(root);
|
|
576
600
|
const slotWarnings = [];
|
|
577
601
|
warnStandaloneSlots(root, slotWarnings);
|
|
578
|
-
pushWarningsDeduped(compilationWarnings, slotWarnings, warningSeen);
|
|
602
|
+
pushWarningsDeduped(compilationWarnings, slotWarnings, warningSeen, compiled.suppressed);
|
|
579
603
|
const applyWarnings = [];
|
|
580
|
-
processApply(root, compiled.theme, applyWarnings);
|
|
581
|
-
pushWarningsDeduped(compilationWarnings, applyWarnings, warningSeen);
|
|
604
|
+
processApply(root, compiled.theme, applyWarnings, from);
|
|
605
|
+
pushWarningsDeduped(compilationWarnings, applyWarnings, warningSeen, compiled.suppressed);
|
|
582
606
|
if (compiled.sections.length > 0) {
|
|
583
607
|
const generatedRoot = postcss2.parse(compiled.sections.join("\n\n"), { from });
|
|
584
608
|
root.prepend(generatedRoot.nodes);
|
|
585
609
|
}
|
|
586
610
|
const cssFnWarnings = [];
|
|
587
611
|
processCSSFunctions(root, compiled.theme, cssFnWarnings);
|
|
588
|
-
pushWarningsDeduped(compilationWarnings, cssFnWarnings, warningSeen);
|
|
612
|
+
pushWarningsDeduped(compilationWarnings, cssFnWarnings, warningSeen, compiled.suppressed);
|
|
589
613
|
for (const warning of compilationWarnings) {
|
|
590
614
|
result.warn(warning);
|
|
591
615
|
}
|