rainbowindex 0.2.0 → 0.2.2

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 CHANGED
@@ -5,6 +5,158 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.2] - 2026-08-13
9
+
10
+ ### Added — editor tooling API (phase 1)
11
+
12
+ - **`rainbowindex/editor` entry** — a new IO-free subpath export for editor
13
+ integrations (VS Code and beyond). Pure computation only: no filesystem,
14
+ network, or module-level mutation, so it runs in browser-based editor hosts
15
+ (vscode.dev) as-is. Ships a version handshake (`version`,
16
+ `EDITOR_API_VERSION`, `editorCapabilities`) so extensions can
17
+ feature-detect whatever version the workspace has installed.
18
+ - **`extractClassCandidates()`** — position-aware variant of the source
19
+ scanner. Returns every class candidate with its absolute source span, its
20
+ collection origin (`attribute` / `helper` / `safelist` / `plain`, with the
21
+ helper name when applicable), and — for variant-group members — the span of
22
+ the group prefix plus the member token inside the braces, so editors can
23
+ squiggle and edit individual members of `hover:{…}` groups. The value set
24
+ is guaranteed identical to `extractClassesFromSource()`; build output is
25
+ byte-for-byte unchanged.
26
+ - **CSS entry detection exports** — `CSS_ENTRY_CANDIDATES` (the CLI/Vite
27
+ probe order, now a pure shared module) plus re-exported `hasRIActivation()`
28
+ and `RI_IMPORT_SPECIFIERS`, letting editor hosts locate the project's CSS
29
+ input with their own file access.
30
+ - **Scanner context exports** — `CLASS_HELPER_NAMES` / `VARIANT_HELPER_NAMES`
31
+ so completion-context detection in editors matches the scanner's behavior.
32
+ - **`analyzeProjectCSS()`** — the theme-only front half of `compileProject`
33
+ (CSS input string → `ResolvedTheme` + directives + warnings), now exported
34
+ for editors. No file IO, no font resolution — cheap enough to re-run on
35
+ every CSS-entry change.
36
+ - **`createClassInspector(theme)`** — single-class validation and
37
+ explanation running the exact resolution the compiler performs, giving the
38
+ intentionally-silent RI-1001 a voice in editors. `validate()` reports
39
+ `unknown-utility` / `unknown-variant` / `invalid-arbitrary` with the
40
+ offending fragment and an OSA-distance typo suggestion (`felx` → `flex`,
41
+ including custom `@utility` and `@custom` names); `explain()` returns the
42
+ parsed structure, root declarations, escaped selector, full rule CSS, and
43
+ sort key. Instances cache per-theme state and resolutions, so
44
+ per-keystroke validation is cheap. Guaranteed: `validate(cls).ok` exactly
45
+ when `compile([cls])` emits a rule.
46
+ - **`listVariants(theme)`** — enumerates every concrete variant the theme
47
+ resolves (pseudo-classes, pseudo-elements, media, breakpoints, container
48
+ queries, special selectors, custom `@custom` variants) plus the open-ended
49
+ pattern families (`data-`, `aria-`, `group-`, …), each tagged with a kind
50
+ and what it wraps. Every concrete entry is guaranteed to resolve.
51
+ - **`parseUtility()` / `findClosest()`** — the class parser (structured
52
+ `ParsedUtility`) and the OSA typo suggester, exported for editor use.
53
+ - **`createEditorSession({ css })`** — the façade an editor holds per
54
+ workspace: theme analysis, inspector, enumeration, token introspection,
55
+ merge snapshot, candidate extraction, and swatches behind one object whose
56
+ caches invalidate together on `setCss()`.
57
+ - **Color swatches** — `resolveColorSwatch(theme, name, stop)` resolves a
58
+ theme color to concrete light/dark values using the same OKLCH math as the
59
+ emitted CSS variables (the dark-mirror computation is now shared via
60
+ `computeDarkStop`), plus `oklchToHex`/`cssColorToHex` conversion for
61
+ completion swatches; handles generative palettes, explicit values, hex,
62
+ light/dark pairs, aliases, and the semantic paper/ink colors.
63
+ `listThemeTokens(theme)` returns one render-ready view of every token
64
+ namespace for sidebar chips.
65
+ - **Structured diagnostics with source spans** — `analyzeProjectCSS()` now
66
+ additionally returns `diagnostics`: the same messages as `warnings`, in the
67
+ same order, each with the parsed `RI-NNNN` code, a severity derived from
68
+ the documented code-range convention (0xxx/2xxx → error), and a
69
+ [start, end) span into the CSS input where the emitter knew one. Directive
70
+ parse problems (`RI-1011/1012/1036/1202`) anchor at their exact site;
71
+ resolver problems anchor at the directive whose body produced them (via
72
+ new opt-in attribution in `resolveDirectives`); post-loop validations stay
73
+ unattributed. `Diagnostic`, `severityForCode()`, `warningCode()`, and
74
+ `diagnosticFromWarning()` ship from `rainbowindex/editor` so editors can
75
+ structure any legacy warning stream. The string arrays remain unchanged
76
+ everywhere.
77
+ - **`analyzeMerge(classes, snapshot?)`** — explains `ri()`'s right-most-wins
78
+ conflict resolution for a pre-tokenized class list: the merged `output`,
79
+ which indices survive, and — for every dropped class — the ascending
80
+ indices of the survivors that claimed its properties (joint domination
81
+ like `text-lg` overridden by `[font-size:16px]` + `leading-tight` lists
82
+ both winners). Runs the exact scan `ri()` runs, via an optional trace that
83
+ costs the hot path one falsy check per property. Powers "this class is
84
+ overridden" editor diagnostics.
85
+ - **`createThemeSnapshot(theme)`** — builds a `CompilationSnapshot` straight
86
+ from a resolved theme (custom text sizes, font slots, color names, custom
87
+ utility property claims) without a compile pass, for theme-accurate
88
+ `analyzeMerge()`/`createRi()` in editors. The registration logic is now
89
+ shared with the compile loop (`registerThemeOnContext`).
90
+ - **`enumerateClassNames(theme)`** — the finite completion universe: every
91
+ static utility, every theme-token expansion (colors × stops, text sizes,
92
+ rounded, shadows, weights, …), and custom `@utility` entries, ~3,400
93
+ classes on the default theme in ~12 ms. Candidates come from a generous
94
+ per-root value-space table (`UTILITY_VALUE_SPACES`) and are then probed
95
+ through the real utility resolver, so every enumerated class is valid by
96
+ construction; infinite families (the spacing scale, numeric values,
97
+ functional custom utilities) are returned as templates. Tests enforce the
98
+ reverse direction: every dispatch root must declare a value space, and
99
+ every merge-table static must enumerate.
100
+
101
+ ### Changed
102
+
103
+ - **`generate-types` rewritten on top of `enumerateClassNames`** — the CLI's
104
+ generated `rainbowindex-env.d.ts` now covers the full utility surface
105
+ (previously a hand-maintained subset: 8 color roots, spacing, text, fonts,
106
+ sizing) and a complete `Variant` union driven by `listVariants`. Plain
107
+ classes are checked against the enumerated finite union plus
108
+ spacing/numeric templates; variant-prefixed classes validate the variant
109
+ name (misspelled variants like `hver:` are now compile errors in strict
110
+ mode).
111
+ - **Fixed: generated types failed to compile** — the previous
112
+ `rainbowindex-env.d.ts` defined `RainbowClass` with a circular
113
+ `Exclude<RainbowClass, …>` self-reference, which TypeScript rejects
114
+ (TS2456), silently breaking `ri()` autocomplete in strict projects. The
115
+ new two-tier `RainbowBase`/`RainbowClass` shape compiles cleanly (~0.7 s
116
+ for a ~3,400-literal union).
117
+ - `[RI-1501]`/`[RI-1502]` (fluid typography) now flow into compile warnings
118
+ when a warning sink is present instead of only the dev console; the dev
119
+ console remains the fallback.
120
+ - Internal: activation detection moved from `directives/index.ts` into a pure
121
+ leaf module (`directives/activation.ts`) so the editor entry and browser
122
+ bundles don't pull the directive resolver's Node-only font machinery into
123
+ their module graph. All existing import paths keep working via re-exports.
124
+ - Internal: `analyzeProjectCSS` moved from `project/pipeline.ts` into a pure
125
+ leaf module (`project/analyze.ts`), and `compileUtility` gained an optional
126
+ failure-detail out-param — both re-exported/behavior-identical, byte-for-
127
+ byte identical CSS output.
128
+ - Internal: the pure font model (types + slot/face factories) moved from the
129
+ `font-providers` barrel into `font-providers/model.ts`; directive parsing
130
+ now imports it (and the font-family safety constants) from leaf modules,
131
+ making the editor entry's module graph structurally free of `node:*`
132
+ imports rather than relying on tree-shaking. The barrel re-exports the
133
+ model, so existing importers are unaffected.
134
+
135
+ ### Fixed
136
+
137
+ - **Dep-advertised `safelistSources` were silently dropped in standard
138
+ install layouts** — auto-discovered safelist patterns resolve to absolute
139
+ paths inside the consumer's `node_modules`, but were globbed in the pass
140
+ that carries the default `node_modules/**` exclude, so they matched
141
+ nothing whenever the dep's real path sat inside the project root — i.e.
142
+ every plain npm/yarn/pnpm install. They now go through the same relaxed
143
+ second glob pass as explicit `@source "node_modules/…"` patterns, which
144
+ drops only that one exclude. (Tests previously passed on macOS only
145
+ because the symlinked tmpdir placed fixture deps outside the literal cwd,
146
+ dodging the cwd-relative exclude; fixtures now realpath the tmp root so
147
+ every platform exercises the real geometry.)
148
+
149
+ ## [0.2.1] - 2026-07-28
150
+
151
+ ### Added — diagnostics
152
+
153
+ - **Vite misuse guard (`[RI-1606]`)** — the default `rainbowindex` export is
154
+ the PostCSS plugin; placing it in Vite's `plugins: []` array previously did
155
+ nothing (no CSS, no error). It now carries an inert Vite-plugin facade that
156
+ throws `[RI-1606]` when Vite resolves config, pointing to
157
+ `import rainbowindex from "rainbowindex/vite"`. The guard is never dispatched
158
+ by PostCSS, so raw PostCSS usage is unaffected.
159
+
8
160
  ## [0.2.0] - 2026-07-16
9
161
 
10
162
  Initial public release. Rainbow Index began as a fork of Tailwind CSS v4; the
package/README.md CHANGED
@@ -298,6 +298,40 @@ If you call `ri()` while a compilation is still in progress (e.g. inside a
298
298
  server-rendering pass that triggers a fresh compile), the runtime emits a
299
299
  throttled `[RI-2004]` warning. That's your signal to switch to `createRi()`.
300
300
 
301
+ ## Editor tooling API
302
+
303
+ `rainbowindex/editor` is an IO-free toolkit for editor integrations — pure
304
+ computation (strings in, structures out) with no `node:*` imports anywhere in
305
+ its module graph, so it runs in browser-based editor hosts (vscode.dev)
306
+ exactly as it does in Node. The host reads files; the entry supplies the
307
+ semantics. Feature-detect via `editorCapabilities` rather than versions —
308
+ integrations load whatever version the workspace has installed.
309
+
310
+ ```ts
311
+ import { createEditorSession } from "rainbowindex/editor";
312
+
313
+ const session = createEditorSession({ css: themeCss });
314
+
315
+ session.diagnostics; // positioned problems in the CSS input
316
+ session.inspector.validate("felx"); // { ok: false, reason: "unknown-utility", suggestion: "flex" }
317
+ session.inspector.explain("sm:px-4"); // parsed structure + generated CSS + sort key
318
+ session.enumerate(); // ~3,400 probe-verified completions + templates
319
+ session.analyzeMerge(["px-2", "px-4"]); // which classes ri() drops, and who overrode them
320
+ session.swatch("brand", 500); // light/dark oklch + hex for completions
321
+ session.extractCandidates(source, path); // class tokens with exact source spans
322
+ session.setCss(nextCss); // theme changed → all caches invalidate together
323
+ ```
324
+
325
+ Everything the session wraps is also exported à la carte —
326
+ `analyzeProjectCSS`, `createClassInspector`, `listVariants`,
327
+ `enumerateClassNames`, `analyzeMerge` + `createThemeSnapshot`,
328
+ `resolveColorSwatch` / `listThemeTokens`, `extractClassCandidates`, and the
329
+ CSS-entry detection helpers (`CSS_ENTRY_CANDIDATES`, `hasRIActivation`).
330
+ Guarantees worth knowing: `validate(cls).ok` exactly when the compiler emits
331
+ a rule for `cls`; every enumerated class is probe-verified against the real
332
+ resolver; `analyzeMerge(...).output` is identical to `ri()`'s result; and
333
+ swatches use the same OKLCH math as the emitted CSS variables.
334
+
301
335
  ## Environment variables
302
336
 
303
337
  | Variable | Effect |
package/dist/browser.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- 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 createRi, f as defaultTheme, g as finalizeCompilationContext, r as registerColorNames, h as registerCustomFontFamilies, i as registerCustomTextSizes, j as registerCustomUtility, k as ri, s as safelist } from './safelist-DRk1XXxi.js';
1
+ 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 createRi, f as defaultTheme, g as finalizeCompilationContext, r as registerColorNames, h as registerCustomFontFamilies, i as registerCustomTextSizes, j as registerCustomUtility, k as ri } from './index-CfDtWufj.js';
2
+ export { s as safelist } from './safelist-CH3_PywB.js';
2
3
 
3
4
  declare function browserEntryUnavailable(): never;
4
5
 
package/dist/browser.mjs CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  registerCustomTextSizes,
14
14
  registerCustomUtility,
15
15
  ri
16
- } from "./chunk-5N4GPK26.mjs";
16
+ } from "./chunk-SOMDX7V6.mjs";
17
17
 
18
18
  // src/entries/browser.ts
19
19
  function browserEntryUnavailable() {
@@ -1,3 +1,9 @@
1
+ import {
2
+ collectProjectClasses,
3
+ finalizeProjectCompilation,
4
+ resolveGoogleFonts,
5
+ validateGlobPattern
6
+ } from "./chunk-FHATRQMN.mjs";
1
7
  import {
2
8
  APPLY_ALIASES,
3
9
  DEFAULT_PROPERTY_GROUP,
@@ -6,10 +12,8 @@ import {
6
12
  PROPERTY_GROUPS,
7
13
  RI_IMPORT_SPECIFIER_ALTERNATION,
8
14
  analyzeProjectCSS,
9
- collectProjectClasses,
10
15
  compileCSSFunctions,
11
16
  expandVariantGroups,
12
- finalizeProjectCompilation,
13
17
  forEachApplyClass,
14
18
  getCustomUtility,
15
19
  hasApplyLikeDirective,
@@ -17,11 +21,9 @@ import {
17
21
  hasRIActivation,
18
22
  parseUtility,
19
23
  pushWarningsDeduped,
20
- resolveGoogleFonts,
21
24
  resolveUtilityDeclarations,
22
- resolveVariant,
23
- validateGlobPattern
24
- } from "./chunk-RPXZ3O6R.mjs";
25
+ resolveVariant
26
+ } from "./chunk-W6XIBM4M.mjs";
25
27
 
26
28
  // src/integrations/postcss/index.ts
27
29
  import postcss from "postcss";
@@ -575,7 +577,7 @@ function processCSSFunctions(root, theme, warnings) {
575
577
  });
576
578
  }
577
579
  var rainbowindex = (options = {}) => {
578
- return {
580
+ const plugin = {
579
581
  postcssPlugin: "rainbowindex",
580
582
  async Once(root, { result }) {
581
583
  try {
@@ -662,6 +664,14 @@ var rainbowindex = (options = {}) => {
662
664
  }
663
665
  }
664
666
  };
667
+ return Object.assign(plugin, {
668
+ name: "rainbowindex",
669
+ config() {
670
+ throw new Error(
671
+ '[RI-1606] The default `rainbowindex` export is the PostCSS plugin, but it was placed in Vite\'s `plugins: []` array where it does nothing. Import the Vite plugin instead: `import rainbowindex from "rainbowindex/vite"`. (For a raw PostCSS setup, keep the default import and register it under `css.postcss.plugins` or in postcss.config.*.)'
672
+ );
673
+ }
674
+ });
665
675
  };
666
676
  rainbowindex.postcss = true;
667
677
  var postcss_default = rainbowindex;