rainbowindex 0.5.1 → 0.7.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +876 -0
  2. package/LICENSE +16 -17
  3. package/NOTICE.md +106 -0
  4. package/README.md +225 -69
  5. package/dist/browser.d.ts +4 -2
  6. package/dist/browser.mjs +12 -6
  7. package/dist/chunk-2T7V5XLK.mjs +912 -0
  8. package/dist/chunk-6OORICWF.mjs +16 -0
  9. package/dist/{chunk-PDORZSQX.mjs → chunk-FJOZJIKB.mjs} +7814 -5174
  10. package/dist/chunk-L56IRO7A.mjs +491 -0
  11. package/dist/chunk-PZDVDEZJ.mjs +196 -0
  12. package/dist/{chunk-4CTJLMYM.mjs → chunk-RC6DDE4L.mjs} +37 -23
  13. package/dist/chunk-TQJYVQPE.mjs +217 -0
  14. package/dist/chunk-W756NVYI.mjs +33 -0
  15. package/dist/chunk-WBESS2ZD.mjs +598 -0
  16. package/dist/{chunk-3HRMFZGE.mjs → chunk-X66Z2YHT.mjs} +2 -1
  17. package/dist/{chunk-4UKFK2GE.mjs → chunk-XQGSG2HK.mjs} +213 -756
  18. package/dist/cli.mjs +1101 -125
  19. package/dist/{context-B9yhJxd5.d.ts → context-DcBtnnan.d.ts} +55 -108
  20. package/dist/editor.d.ts +82 -421
  21. package/dist/editor.mjs +68 -363
  22. package/dist/eslint.d.ts +16 -0
  23. package/dist/eslint.mjs +32 -0
  24. package/dist/{index-Dx-NpFFx.d.ts → imports-C9esHd5Q.d.ts} +98 -81
  25. package/dist/index-CNqdL5U0.d.ts +56 -0
  26. package/dist/index-Czx-EUwh.d.ts +138 -0
  27. package/dist/index-DW8YSxTz.d.ts +104 -0
  28. package/dist/index.d.ts +49 -5
  29. package/dist/index.mjs +40 -13
  30. package/dist/oxlint.d.ts +21 -3
  31. package/dist/oxlint.mjs +19 -1
  32. package/dist/recipe.d.ts +111 -0
  33. package/dist/recipe.mjs +71 -0
  34. package/dist/safelist-CH3_PywB.d.ts +43 -0
  35. package/dist/session-CMaskdB7.d.ts +543 -0
  36. package/dist/tailwind.css +644 -0
  37. package/dist/theme-CIZiGlce.d.ts +115 -0
  38. package/dist/vite.d.ts +10 -1
  39. package/dist/vite.mjs +273 -113
  40. package/package.json +27 -5
  41. package/dist/chunk-F4VCBISU.mjs +0 -1866
  42. package/dist/chunk-RU4756NG.mjs +0 -243
  43. package/dist/safelist-DAkKuxCk.d.ts +0 -96
@@ -1,4 +1,4 @@
1
- import { C as ColorDefinition, j as DarkModeConfig, k as CornerShape, A as AnimationDefinition, F as FluidConfig, b as CompilationSnapshot } from './context-B9yhJxd5.js';
1
+ import { C as ColorDefinition, D as DarkModeConfig, b as CornerShape, A as AnimationDefinition, F as FluidConfig } from './index-Czx-EUwh.js';
2
2
 
3
3
  /** Provider discriminant for a slot, derived from its faces. */
4
4
  type FontProviderKind = "google" | "system" | "local" | "manual";
@@ -57,23 +57,21 @@ interface FontMetricsConfig {
57
57
  descent?: number;
58
58
  lineGap?: number;
59
59
  }
60
-
61
60
  /**
62
- * Font loading system — @font directive processing, @font-face generation,
63
- * metrics-adjusted fallbacks for zero CLS.
61
+ * Whether any loaded font can render `weight` — the check behind RI-1504.
62
+ *
63
+ * A slot's faces are the authority: their `weight` descriptor is exactly what
64
+ * the emitted @font-face (or the Google URL) asks for, so a weight outside it
65
+ * is a weight the browser has to synthesize.
64
66
  *
65
- * A slot (sans/serif/mono/custom) maps to one --font-<slot> variable and one
66
- * family name, but can own multiple faces — e.g. an upright + an italic file,
67
- * or split unicode ranges. Each FontFace emits one @font-face for local
68
- * providers; google/system/manual slots carry a single face.
67
+ * Deliberately fails open, since `font-<n>` names no family and a page can
68
+ * load several: no faces to check, a system/manual slot (the OS font carries
69
+ * every weight), or a single covering slot all count as available.
69
70
  */
70
-
71
- interface FontOutput {
72
- imports: string[];
73
- fontFaces: string[];
74
- variables: string[];
75
- warnings: string[];
76
- }
71
+ declare function weightIsLoaded(weight: number, fonts: readonly FontSlot[]): boolean;
72
+ /** Human-readable weight inventory for the RI-1504 message:
73
+ * `Inter 300–900; Fira Code 400, 700`. */
74
+ declare function describeLoadedWeights(fonts: readonly FontSlot[]): string;
77
75
 
78
76
  /**
79
77
  * Raw-extractable directive names — the single source for the DirectiveType
@@ -165,6 +163,10 @@ interface ResolvedTheme {
165
163
  * `roundedShape` is null.
166
164
  */
167
165
  readonly roundedShapeScale: number;
166
+ /** Named radii from `@rounded { roof: 24px; }` — each one makes the class
167
+ * `rounded-<name>` and the token `--rounded-<name>`. A name that matches a
168
+ * built-in radius keyword replaces it; RI-1124 warns at definition. */
169
+ readonly radii: Readonly<Record<string, string>>;
168
170
  readonly shadows: Readonly<Record<string, string>>;
169
171
  readonly weights: Readonly<Record<string, number>>;
170
172
  readonly easing: Readonly<Record<string, string>>;
@@ -174,6 +176,10 @@ interface ResolvedTheme {
174
176
  readonly fluid: Readonly<FluidConfig>;
175
177
  readonly textFluid?: Readonly<FluidConfig>;
176
178
  readonly spacingFluid?: Readonly<FluidConfig>;
179
+ /** Named viewport ranges from `@fluid <name> { min; max; }` — each one makes
180
+ * the scope class `fluid-<name>` and the tokens `--fluid-<name>-{min,max}`.
181
+ * Ranges carry no unit: the ramp unit is baked per family. */
182
+ readonly fluidRanges: Readonly<Record<string, Readonly<FluidConfig>>>;
177
183
  readonly fonts: readonly FontSlot[];
178
184
  readonly preflight: Readonly<PreflightConfig>;
179
185
  readonly customUtilities: readonly CustomUtility[];
@@ -189,76 +195,87 @@ interface ResolvedTheme {
189
195
  readonly warnings: readonly string[];
190
196
  }
191
197
 
192
- interface CompiledRule {
193
- /** The original class name (escaped for CSS selector). */
194
- selector: string;
195
- /** Sort key for deterministic ordering. */
196
- sortKey: number;
197
- /** CSS declarations as a string block. */
198
- css: string;
199
- }
200
- interface CompilationResult {
201
- /** All compiled CSS rules. */
202
- rules: CompiledRule[];
203
- /** @keyframes blocks needed. */
204
- keyframes: string[];
205
- /** @property declarations needed. */
206
- properties: string[];
207
- /** Map of used color hue → set of used suffixes (for token pruning). */
208
- usedColorStops: Map<string, Set<number>>;
209
- /** Set of used text size names (for token pruning). */
210
- usedTextSizes: Set<string>;
211
- /** Set of used font slot names (for token pruning). */
212
- usedFonts: Set<string>;
213
- /** Set of used rounded value names (for token pruning). */
214
- /** Set of used shadow names (for token pruning). */
215
- usedShadows: Set<string>;
216
- /** Set of used animation shorthand names (for token pruning). */
217
- usedAnimations: Set<string>;
218
- /** Warnings emitted during compilation. */
219
- warnings: string[];
220
- }
221
-
222
198
  /**
223
- * Build a CompilationSnapshot straight from a resolved theme — no compile
224
- * pass, no module-level state. Editor tooling pairs this with
225
- * analyzeMerge()/createRi() for theme-accurate merge semantics.
226
- */
227
- declare function createThemeSnapshot(theme: ResolvedTheme): CompilationSnapshot;
228
- /**
229
- * Create an isolated compiler instance for SSR / concurrent-compilation
230
- * environments. Returns a `compile()` function that does NOT touch module-level
231
- * state, and a `createRi()` that produces a merge function bound to the
232
- * compilation's snapshot.
199
+ * `@import` inlining for the directive analyzer.
200
+ *
201
+ * The analyzer reads directives out of one CSS string. Until an import is
202
+ * inlined, a `@color` block living in `./tokens.css` — or in a preset shipped
203
+ * by a package — is invisible to it: only the Vite path ever saw imported
204
+ * text, because Vite resolves CSS imports before PostCSS plugins run.
205
+ *
206
+ * This module closes that gap for every other surface. It is deliberately
207
+ * IO-free: the caller supplies a resolver, so the same code serves the CLI
208
+ * (filesystem), the PostCSS plugin (filesystem), and an editor host (its own
209
+ * open-document map) without any of them dragging `node:fs` into a browser
210
+ * bundle. `resolve-import.ts` holds the Node resolver.
233
211
  *
234
- * **Isolation scope:** Compilation context, variant map cache, and font output
235
- * cache are fully isolated per instance. Google Fonts metadata (from fonts.ts)
236
- * is intentionally shared read-only across instances — it is populated once
237
- * via atomic swap and never mutated afterward, so concurrent reads are safe.
212
+ * What is replaced, and what is left alone:
238
213
  *
239
- * **Font output cache lifecycle:** `fontOutputCache` is cleared at the start
240
- * of each `compile()` call, so it only caches within a single compilation pass.
241
- * If the same compiler instance is reused across compilations (the expected SSR
242
- * pattern), each compilation starts with a fresh font cache.
214
+ * - `@import "./tokens.css";` and `@import "pkg/preset.css";` — inlined.
215
+ * - `@import "rainbowindex";` — left in place at the entry, since that is what
216
+ * activates the compiler; dropped inside an imported file, so a preset that
217
+ * imports the package cannot activate it twice. `rainbowindex/tailwind.css`
218
+ * activates too, but it is a stylesheet of directives rather than a marker,
219
+ * so it is inlined like any other package preset.
220
+ * - `@import url("https://…")`, `@import "/site.css"` — left alone. Those are
221
+ * URLs for the browser to fetch, not files on disk.
222
+ * - `@import "a.css" screen;`, `… layer(x);`, `… supports(…);` — left alone
223
+ * and warned (RI-1045). Their contents apply conditionally, and directives
224
+ * have no conditional form, so silently hoisting them would be a lie.
243
225
  *
244
- * @example
245
- * ```ts
246
- * import { createCompiler } from "rainbowindex";
226
+ * Inlining is for READING. Whether the inlined text is also emitted is the
227
+ * caller's business: the PostCSS plugin builds its output from the AST, so
228
+ * nothing is duplicated there, while the CLI and `compileProject` join the
229
+ * inlined user CSS into their output once, in import order.
230
+ *
231
+ * One thing the inliner changes rather than copies: comments inside a PACKAGE
232
+ * import are dropped, and comments in the project's own files are not. A
233
+ * package's stylesheet is consumed as CSS, and its notes are addressed to
234
+ * whoever opens that package — the Tailwind preset alone was contributing
235
+ * 4.3 KB of section headings to every unminified build. Package-ness is
236
+ * inherited down the subtree, so a package's own relative imports are stripped
237
+ * too. See `stripCSSComments` and docs/preset-protocol.md.
238
+ */
239
+ /** A file the resolver found: its identity, and its text. */
240
+ interface ImportResolution {
241
+ /**
242
+ * Identity of the resolved file — an absolute path for the Node resolver.
243
+ * Used for cycle detection and as the base for the file's own imports, so
244
+ * it must be stable: the same file has to produce the same string.
245
+ */
246
+ path: string;
247
+ content: string;
248
+ }
249
+ /**
250
+ * Turn an `@import` specifier into a file, or null when it cannot be found.
251
+ * `from` is the identity of the importing file, or undefined at the entry.
252
+ */
253
+ type ImportResolver = (specifier: string, from: string | undefined) => ImportResolution | null;
254
+ interface InlineImportsOptions {
255
+ resolve: ImportResolver;
256
+ /** Identity of the CSS being inlined, so its relative imports resolve. */
257
+ from?: string;
258
+ /** How deep the import graph may nest before RI-1043. */
259
+ maxDepth?: number;
260
+ /** Ceiling on total inlined bytes before RI-1044. */
261
+ maxBytes?: number;
262
+ }
263
+ interface InlineImportsResult {
264
+ css: string;
265
+ warnings: string[];
266
+ /**
267
+ * Every file inlined, in first-visit order. A watcher adds these to what it
268
+ * watches; without them, editing an imported token file changes nothing.
269
+ */
270
+ files: string[];
271
+ }
272
+ /**
273
+ * Replace resolvable `@import` at-rules with the text they name, recursively,
274
+ * so the directive analyzer sees one stylesheet.
247
275
  *
248
- * const compiler = createCompiler();
249
- * const result = compiler.compile(classNames, theme);
250
- * const ri = compiler.createRi();
251
- * ```
276
+ * Returns the input unchanged when there is nothing to inline, which keeps the
277
+ * analyzer's single-entry memo hitting on repeat builds.
252
278
  */
253
- declare function createCompiler(): {
254
- /** `authored` names the classes the user wrote by hand (`@source inline`,
255
- * `@apply`, a caller-supplied list). Omit it to treat every class as
256
- * authored — correct for callers who assembled the list themselves. */
257
- compile: (classNames: Iterable<string>, theme: ResolvedTheme, authored?: ReadonlySet<string>) => CompilationResult;
258
- createRi: () => (...inputs: (string | false | null | undefined)[]) => string;
259
- /** Isolated font output cache for this compiler instance. Pass to
260
- * `assembleSections()` to avoid sharing module-level font state. */
261
- fontOutputCache: Map<string, FontOutput>;
262
- };
279
+ declare function inlineDirectiveImports(css: string, options: InlineImportsOptions): InlineImportsResult;
263
280
 
264
- export { type CompilationResult as C, type ParsedDirective as P, type ResolvedTheme as R, type CompiledRule as a, createThemeSnapshot as b, createCompiler as c };
281
+ export { type ImportResolver as I, type ParsedDirective as P, type ResolvedTheme as R, type ImportResolution as a, type InlineImportsOptions as b, type InlineImportsResult as c, describeLoadedWeights as d, inlineDirectiveImports as i, weightIsLoaded as w };
@@ -0,0 +1,56 @@
1
+ import { a as CompilationSnapshot } from './context-DcBtnnan.js';
2
+
3
+ /**
4
+ * ri() — class merge function.
5
+ * Replaces both tailwind-merge and clsx.
6
+ *
7
+ * Re-exported from the package's main and browser entries as `ri()`.
8
+ * Right-to-left scan: rightmost class wins when two classes set the same CSS property.
9
+ *
10
+ * This file is the pure merge runtime. Its siblings hold the other merge
11
+ * concepts: props.ts (claim data), resolve.ts (dual-mode claim resolution),
12
+ * context.ts (compilation-context lifecycle + published state), analyze.ts
13
+ * (editor-only merge diagnostics).
14
+ *
15
+ * ## Concurrency
16
+ *
17
+ * The default `ri()` export uses module-level state published by
18
+ * `finalizeCompilationContext()`. This is safe for single-compilation
19
+ * environments (typical browser usage, single Vite build, PostCSS).
20
+ *
21
+ * In multi-tenant / SSR / concurrent-compilation environments, use
22
+ * `createRi(snapshot)` instead — it captures a frozen snapshot of the
23
+ * compilation state and uses its own independent cache:
24
+ *
25
+ * const snapshot = finalizeCompilationContext(ctx);
26
+ * const ri = createRi(snapshot);
27
+ */
28
+ /** Anything `ri()` accepts: class strings, falsy holes, and nested arrays.
29
+ * Exported because `rainbowindex/recipe` builds its own inputs from it. */
30
+ type ClassInput = string | false | null | undefined | ClassInput[];
31
+
32
+ /**
33
+ * Merge class names with conflict resolution (replaces both tailwind-merge and clsx).
34
+ * Rightmost class wins when two classes set the same CSS property.
35
+ * Falsy values are filtered.
36
+ *
37
+ * @example
38
+ * ri('p-2 bg-red-500', 'p-4') // → 'bg-red-500 p-4'
39
+ * ri('px-2 py-1', 'p-4') // → 'p-4' (shorthand wins)
40
+ * ri('flex', isActive && 'bg-blue-500') // → 'flex bg-blue-500'
41
+ * ri('text-lg text-red-500') // → 'text-lg text-red-500' (different properties)
42
+ */
43
+ declare function ri(...inputs: ClassInput[]): string;
44
+ /**
45
+ * Create an isolated ri() instance bound to a specific compilation snapshot.
46
+ * Use this in SSR or multi-compilation environments where the global ri()
47
+ * would be corrupted by concurrent compilations.
48
+ *
49
+ * @example
50
+ * const snapshot = finalizeCompilationContext(ctx);
51
+ * const ri = createRi(snapshot);
52
+ * ri('p-2 bg-red-500', 'p-4') // → 'bg-red-500 p-4'
53
+ */
54
+ declare function createRi(snapshot?: CompilationSnapshot): (...inputs: ClassInput[]) => string;
55
+
56
+ export { type ClassInput as C, createRi as c, ri as r };
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Generative color system — color domain model, OKLCH ramp generation,
3
+ * and light-dark() pairing.
4
+ *
5
+ * 2 numbers (chroma + hue) → 19-stop palette with automatic dark mode.
6
+ *
7
+ * The ramp is sampled from a fixed reference profile (`L_PROFILE` / `C_SHAPE` /
8
+ * `H_DRIFT`, captured from the reference palette): lightness is a curved,
9
+ * compressed scale (low suffix → light, high → dark), chroma is an asymmetric
10
+ * bell peaking at stop 500, and hue is near-flat. Dark mode is a simple ramp
11
+ * reversal — the dark value is the stop the ramp reaches at the mirror position
12
+ * (`1000 - suffix`), so stop 500 pivots to itself.
13
+ */
14
+ /** Per-color dark mode override strategy. */
15
+ type ColorDarkOverride = {
16
+ strategy: "mirror";
17
+ } | {
18
+ strategy: "fixed";
19
+ } | {
20
+ strategy: "shift";
21
+ chromaDelta: number;
22
+ hueDelta: number;
23
+ };
24
+ /**
25
+ * Color definition — discriminated union supporting:
26
+ * - Generative: `brand: 0.18 330;` → 19-stop palette with auto dark mode
27
+ * - Explicit: `accent: oklch(0.72 0.21 330);` → single color value
28
+ * - Pair: `surface: oklch(0.98 0.01 260) / oklch(0.15 0.01 260);` → light/dark pair
29
+ * - Alias: `theme: brand;` → references another color's palette via var()
30
+ */
31
+ type ColorDefinition = {
32
+ type: "generative";
33
+ chroma: number;
34
+ hue: number;
35
+ dark?: ColorDarkOverride;
36
+ inline?: boolean;
37
+ parabolic?: boolean;
38
+ chromaBoost?: boolean;
39
+ } | {
40
+ type: "explicit";
41
+ value: string;
42
+ } | {
43
+ type: "keyword";
44
+ value: string;
45
+ } | {
46
+ type: "pair";
47
+ light: string;
48
+ dark: string;
49
+ } | {
50
+ type: "alias";
51
+ source: string;
52
+ };
53
+ /**
54
+ * How `dark:` and `light:` decide they apply.
55
+ *
56
+ * The point of the choice is that it has to agree with when the *tokens* flip.
57
+ * Tokens use `light-dark()`, which follows `color-scheme`, which the shipped
58
+ * preflight drives from `html[data-appearance]` on top of the OS preference. A
59
+ * strategy that disagrees with that gives a build two theme switches that
60
+ * disagree, which is what this replaced.
61
+ *
62
+ * - `media` — `@media (prefers-color-scheme: dark)`. The OS preference alone.
63
+ * The historical behaviour, and the default.
64
+ * - `appearance` — matches exactly when `light-dark()` flips under the shipped
65
+ * preflight: an explicit `html[data-appearance="dark"]`, or the OS preference
66
+ * where no attribute has overridden it. Needs two rules; see `alternate` on
67
+ * {@link VariantWrapper}.
68
+ * - `selector` — a class or any selector you toggle yourself, the strategy
69
+ * Tailwind projects arrive with. The OS preference is ignored, as it is
70
+ * there.
71
+ */
72
+ type DarkVariantStrategy = {
73
+ readonly kind: "media";
74
+ } | {
75
+ readonly kind: "appearance";
76
+ } | {
77
+ readonly kind: "selector";
78
+ readonly selector: string;
79
+ };
80
+ interface DarkModeConfig {
81
+ mode: "auto" | "off";
82
+ chromaBoost: number;
83
+ hueShift: number;
84
+ variant: DarkVariantStrategy;
85
+ }
86
+
87
+ /**
88
+ * Default theme values — the static data that ships if the user writes no
89
+ * directives. Only the colour palette and the spacing base ship a value; every
90
+ * named scale starts empty and is filled by its directive.
91
+ */
92
+
93
+ interface TextSize {
94
+ fontSize: string;
95
+ lineHeight: string;
96
+ }
97
+ /** Viewport units, and the container-query units that track a container
98
+ * instead. Keep in step with `FLUID_UNITS` in directives/resolver.ts, which
99
+ * validates the `unit` a `@fluid` block asks for. */
100
+ type FluidUnit = "vw" | "vi" | "vmin" | "vmax" | "cqw" | "cqi" | "cqmin" | "cqmax";
101
+ interface FluidConfig {
102
+ min?: string;
103
+ max?: string;
104
+ unit?: FluidUnit;
105
+ multiplier?: number;
106
+ }
107
+ interface AnimationDefinition {
108
+ shorthand: string;
109
+ keyframes: string;
110
+ }
111
+ interface Theme {
112
+ spacing: {
113
+ base: string;
114
+ };
115
+ colors: Record<string, ColorDefinition>;
116
+ text: Record<string, TextSize>;
117
+ breakpoints: Record<string, string>;
118
+ shadows: Record<string, string>;
119
+ weights: Record<string, number>;
120
+ easing: Record<string, string>;
121
+ fluid: FluidConfig;
122
+ animations: Record<string, AnimationDefinition>;
123
+ blur: Record<string, string>;
124
+ }
125
+ /**
126
+ * Keyword corner-shape values. `superellipse(N)` is represented separately
127
+ * as `{ superellipse: N }` since the numeric parameter isn't a keyword.
128
+ * Single source for the type, the scale table below, and the @rounded
129
+ * modifier parser (directives/parsers.ts).
130
+ */
131
+ declare const CORNER_SHAPE_KEYWORDS: readonly ["round", "scoop", "bevel", "notch", "square", "squircle"];
132
+ type CornerShapeKeyword = (typeof CORNER_SHAPE_KEYWORDS)[number];
133
+ type CornerShape = CornerShapeKeyword | {
134
+ superellipse: number;
135
+ };
136
+ declare const defaultTheme: Theme;
137
+
138
+ export { type AnimationDefinition as A, type ColorDefinition as C, type DarkModeConfig as D, type FluidConfig as F, type TextSize as T, type Theme as a, type CornerShape as b, defaultTheme as d };
@@ -0,0 +1,104 @@
1
+ import { a as CompilationSnapshot } from './context-DcBtnnan.js';
2
+ import { R as ResolvedTheme } from './imports-C9esHd5Q.js';
3
+
4
+ /**
5
+ * Pure `@font-face` emission — no network, no cache, no `node:` anything.
6
+ *
7
+ * Split out of `index.ts` so the CSS assembly graph stays browser-safe. The
8
+ * barrel next door re-exports both halves, but it also re-exports the Google
9
+ * client, which reaches `node:crypto` and `node:fs` through its on-disk
10
+ * metadata cache. `assembly.ts` needs only the emission half, and
11
+ * `rainbowindex/editor` needs `assembly.ts`, so importing the barrel there
12
+ * would drag the whole fetch/cache machinery into a bundle meant to run in
13
+ * vscode.dev and in the playground. Everything here is strings in, strings
14
+ * out: the network resolver hands its answers to the theme long before
15
+ * anything in this file runs.
16
+ */
17
+
18
+ interface FontOutput {
19
+ imports: string[];
20
+ fontFaces: string[];
21
+ variables: string[];
22
+ warnings: string[];
23
+ }
24
+
25
+ interface CompiledRule {
26
+ /** The original class name (escaped for CSS selector). */
27
+ selector: string;
28
+ /** Sort key for deterministic ordering. */
29
+ sortKey: number;
30
+ /** CSS declarations as a string block. */
31
+ css: string;
32
+ }
33
+ interface CompilationResult {
34
+ /** All compiled CSS rules. */
35
+ rules: CompiledRule[];
36
+ /** @keyframes blocks needed. */
37
+ keyframes: string[];
38
+ /** @property declarations needed. */
39
+ properties: string[];
40
+ /** Map of used color hue → set of used suffixes (for token pruning). */
41
+ usedColorStops: Map<string, Set<number>>;
42
+ /**
43
+ * Whole `--color-<name>` token names referenced anywhere, generative stops
44
+ * included. `usedColorStops` cannot stand in for this: an explicit or pair
45
+ * entry is keyed by its undivided name, and a stop-less reference such as
46
+ * `var(--color-surface)` has no suffix for that map to record at all.
47
+ */
48
+ usedColorNames: Set<string>;
49
+ /** Set of used text size names (for token pruning). */
50
+ usedTextSizes: Set<string>;
51
+ /** Set of used font slot names (for token pruning). */
52
+ usedFonts: Set<string>;
53
+ /** Set of used rounded value names (for token pruning). */
54
+ /** Set of used shadow names (for token pruning). */
55
+ usedShadows: Set<string>;
56
+ /** Set of used animation shorthand names (for token pruning). */
57
+ usedAnimations: Set<string>;
58
+ /** Warnings emitted during compilation. */
59
+ warnings: string[];
60
+ }
61
+
62
+ /**
63
+ * Build a CompilationSnapshot straight from a resolved theme — no compile
64
+ * pass, no module-level state. Editor tooling pairs this with
65
+ * analyzeMerge()/createRi() for theme-accurate merge semantics.
66
+ */
67
+ declare function createThemeSnapshot(theme: ResolvedTheme): CompilationSnapshot;
68
+ /**
69
+ * Create an isolated compiler instance for SSR / concurrent-compilation
70
+ * environments. Returns a `compile()` function that does NOT touch module-level
71
+ * state, and a `createRi()` that produces a merge function bound to the
72
+ * compilation's snapshot.
73
+ *
74
+ * **Isolation scope:** Compilation context, variant map cache, and font output
75
+ * cache are fully isolated per instance. Google Fonts metadata (from fonts.ts)
76
+ * is intentionally shared read-only across instances — it is populated once
77
+ * via atomic swap and never mutated afterward, so concurrent reads are safe.
78
+ *
79
+ * **Font output cache lifecycle:** `fontOutputCache` is cleared at the start
80
+ * of each `compile()` call, so it only caches within a single compilation pass.
81
+ * If the same compiler instance is reused across compilations (the expected SSR
82
+ * pattern), each compilation starts with a fresh font cache.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * import { createCompiler } from "rainbowindex";
87
+ *
88
+ * const compiler = createCompiler();
89
+ * const result = compiler.compile(classNames, theme);
90
+ * const ri = compiler.createRi();
91
+ * ```
92
+ */
93
+ declare function createCompiler(): {
94
+ /** `authored` names the classes the user wrote by hand (`@source inline`,
95
+ * `@apply`, a caller-supplied list). Omit it to treat every class as
96
+ * authored — correct for callers who assembled the list themselves. */
97
+ compile: (classNames: Iterable<string>, theme: ResolvedTheme, authored?: ReadonlySet<string>) => CompilationResult;
98
+ createRi: () => (...inputs: (string | false | null | undefined)[]) => string;
99
+ /** Isolated font output cache for this compiler instance. Pass to
100
+ * `assembleSections()` to avoid sharing module-level font state. */
101
+ fontOutputCache: Map<string, FontOutput>;
102
+ };
103
+
104
+ export { type CompilationResult as C, type CompiledRule as a, createThemeSnapshot as b, createCompiler as c };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,11 @@
1
+ export { C as CompilationResult, a as CompiledRule, c as createCompiler } from './index-DW8YSxTz.js';
1
2
  import { PluginCreator } from 'postcss';
2
- export { C as ColorDefinition, a as CompilationContext, b as CompilationSnapshot, D as DEFAULT_TEXT_SIZES, 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 './context-B9yhJxd5.js';
3
- export { c as createRi, r as ri, s as safelist } from './safelist-DAkKuxCk.js';
4
- import { R as ResolvedTheme, P as ParsedDirective } from './index-Dx-NpFFx.js';
5
- export { C as CompilationResult, a as CompiledRule, c as createCompiler } from './index-Dx-NpFFx.js';
3
+ export { C as CompilationContext, a as CompilationSnapshot, S as SerializedSnapshot, c as createCompilationContext, f as finalizeCompilationContext, h as hydrateSnapshot, p as publishSnapshot, r as registerColorNames, b as registerCustomFontFamilies, d as registerCustomTextSizes, e as registerCustomUtility, s as serializeSnapshot } from './context-DcBtnnan.js';
4
+ export { c as createRi, r as ri } from './index-CNqdL5U0.js';
5
+ import { R as ResolvedTheme, P as ParsedDirective, I as ImportResolver } from './imports-C9esHd5Q.js';
6
+ export { a as ImportResolution, b as InlineImportsOptions, c as InlineImportsResult, i as inlineDirectiveImports } from './imports-C9esHd5Q.js';
7
+ export { s as safelist } from './safelist-CH3_PywB.js';
8
+ export { C as ColorDefinition, F as FluidConfig, T as TextSize, a as Theme, d as defaultTheme } from './index-Czx-EUwh.js';
6
9
 
7
10
  interface RainbowIndexOptions {
8
11
  sources?: string[];
@@ -21,6 +24,9 @@ interface FinalizeProjectResult {
21
24
  theme: ResolvedTheme;
22
25
  directives: ParsedDirective[];
23
26
  warnings: string[];
27
+ /** Codes silenced for this entry by `/* ri-disable … *\/`. A consumer that
28
+ * pushes further warnings into `warnings` must push through this too. */
29
+ suppressed: ReadonlySet<string>;
24
30
  }
25
31
 
26
32
  interface SourceEntry {
@@ -33,9 +39,47 @@ interface CompileProjectOptions {
33
39
  classNames?: Iterable<string>;
34
40
  resolveFonts?: FontResolver;
35
41
  processCssFunctions?: boolean;
42
+ /** Path of the CSS entry — the base for relative `@import` specifiers. */
43
+ cssPath?: string;
44
+ /**
45
+ * How `@import` specifiers become files, so directives in imported files
46
+ * are read. Defaults to the filesystem once `cssPath` says where the entry
47
+ * lives; with neither, imports pass through untouched as they always have.
48
+ * Pass `null` to keep that behavior even when `cssPath` is set.
49
+ */
50
+ resolveImport?: ImportResolver | null;
36
51
  }
37
52
  /** compileProject returns the pipeline result unmodified — one shape, two names. */
38
53
  type CompileProjectResult = FinalizeProjectResult;
39
54
  declare function compileProject(options: CompileProjectOptions): Promise<CompileProjectResult>;
40
55
 
41
- export { type CompileProjectOptions, type CompileProjectResult, type RainbowIndexOptions, compileProject, rainbowindex as default };
56
+ /**
57
+ * Node resolver for `@import` inlining — the only IO half of the feature.
58
+ *
59
+ * Kept apart from `imports.ts` so the inliner itself stays importable from the
60
+ * editor entry and from browser bundles. Nothing here is reachable from those:
61
+ * only the CLI, the PostCSS plugin, and `compileProject` construct a resolver.
62
+ *
63
+ * Two specifier shapes resolve:
64
+ *
65
+ * - `./tokens.css`, `../shared/theme.css` — relative to the importing file, or
66
+ * to `cwd` for the entry when it has no path of its own.
67
+ * - `pkg/preset.css` — through `require.resolve`, so a package's `exports` map
68
+ * decides, exactly as it would for JavaScript. That is what makes
69
+ * `@import "rainbowindex/tailwind.css"` work without knowing where the
70
+ * package lives.
71
+ *
72
+ * Everything else — remote URLs, site-root paths — is filtered out by the
73
+ * inliner before it ever calls this.
74
+ */
75
+
76
+ /**
77
+ * Build a resolver rooted at `cwd`. Failures — missing file, unreadable file,
78
+ * an oversized one, a bare specifier no package provides — all return null, and
79
+ * the inliner turns that into one RI-1041 naming the specifier.
80
+ */
81
+ declare function createNodeImportResolver(options: {
82
+ cwd: string;
83
+ }): ImportResolver;
84
+
85
+ export { type CompileProjectOptions, type CompileProjectResult, ImportResolver, type RainbowIndexOptions, compileProject, createNodeImportResolver, rainbowindex as default };