rainbowindex 0.2.1 → 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 +141 -0
- package/README.md +34 -0
- package/dist/browser.d.ts +2 -1
- package/dist/browser.mjs +1 -1
- package/dist/{chunk-5ECTKN44.mjs → chunk-CUUW2K35.mjs} +8 -6
- package/dist/chunk-FHATRQMN.mjs +1635 -0
- package/dist/chunk-KYDEHYIE.mjs +691 -0
- package/dist/{chunk-5N4GPK26.mjs → chunk-SOMDX7V6.mjs} +74 -16
- package/dist/{chunk-RPXZ3O6R.mjs → chunk-W6XIBM4M.mjs} +6118 -7201
- package/dist/cli.mjs +72 -40
- package/dist/editor.d.ts +464 -0
- package/dist/editor.mjs +402 -0
- package/dist/{safelist-DRk1XXxi.d.ts → index-CfDtWufj.d.ts} +29 -43
- package/dist/index-DK6APAGD.d.ts +260 -0
- package/dist/index.d.ts +5 -253
- package/dist/index.mjs +8 -6
- package/dist/safelist-CH3_PywB.d.ts +43 -0
- package/dist/vite.mjs +4 -3
- package/package.json +7 -3
package/dist/cli.mjs
CHANGED
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
CSS_ENTRY_CANDIDATES,
|
|
4
|
+
enumerateClassNames
|
|
5
|
+
} from "./chunk-KYDEHYIE.mjs";
|
|
2
6
|
import {
|
|
3
7
|
DEFAULT_EXCLUDES,
|
|
4
8
|
DEFAULT_PATTERNS,
|
|
5
|
-
MAX_DIRECTIVE_INPUT_SIZE,
|
|
6
|
-
analyzeProjectCSS,
|
|
7
9
|
collectProjectClasses,
|
|
8
|
-
extractDirectives,
|
|
9
10
|
finalizeProjectCompilation,
|
|
10
11
|
getFontPreloadLinks,
|
|
11
|
-
hasApplyLikeDirective,
|
|
12
|
-
hasRIActivation,
|
|
13
|
-
resolveDirectives,
|
|
14
12
|
resolveGoogleFonts,
|
|
15
13
|
validateGlobPattern
|
|
16
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-FHATRQMN.mjs";
|
|
15
|
+
import {
|
|
16
|
+
MAX_DIRECTIVE_INPUT_SIZE,
|
|
17
|
+
analyzeProjectCSS,
|
|
18
|
+
extractDirectives,
|
|
19
|
+
hasApplyLikeDirective,
|
|
20
|
+
hasRIActivation,
|
|
21
|
+
listVariants,
|
|
22
|
+
resolveDirectives
|
|
23
|
+
} from "./chunk-W6XIBM4M.mjs";
|
|
17
24
|
import {
|
|
18
25
|
devWarn
|
|
19
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-SOMDX7V6.mjs";
|
|
20
27
|
|
|
21
28
|
// src/entries/cli.ts
|
|
22
29
|
import { realpathSync } from "fs";
|
|
@@ -314,21 +321,9 @@ Examples:
|
|
|
314
321
|
import { existsSync } from "fs";
|
|
315
322
|
import { readFile, stat } from "fs/promises";
|
|
316
323
|
import { resolve as resolve2 } from "path";
|
|
317
|
-
var CSS_CANDIDATES = Object.freeze([
|
|
318
|
-
"src/index.css",
|
|
319
|
-
"src/style.css",
|
|
320
|
-
"src/styles.css",
|
|
321
|
-
"src/app.css",
|
|
322
|
-
"src/global.css",
|
|
323
|
-
"index.css",
|
|
324
|
-
"style.css",
|
|
325
|
-
"styles.css",
|
|
326
|
-
"app.css",
|
|
327
|
-
"global.css"
|
|
328
|
-
]);
|
|
329
324
|
var MAX_CSS_FILE_SIZE = MAX_DIRECTIVE_INPUT_SIZE;
|
|
330
325
|
async function findCSSFileAsync(cwd) {
|
|
331
|
-
const candidates =
|
|
326
|
+
const candidates = CSS_ENTRY_CANDIDATES;
|
|
332
327
|
const results = await Promise.all(
|
|
333
328
|
candidates.map(async (candidate) => {
|
|
334
329
|
const full = resolve2(cwd, candidate);
|
|
@@ -452,19 +447,37 @@ async function generateTypes(opts, cwd) {
|
|
|
452
447
|
return false;
|
|
453
448
|
});
|
|
454
449
|
};
|
|
450
|
+
const literalSafe = (names) => names.filter((n) => !n.includes('"') && !n.includes("\\"));
|
|
451
|
+
const enumeration = enumerateClassNames(theme);
|
|
452
|
+
const variants = listVariants(theme);
|
|
455
453
|
const colorNames = validateNames(Object.keys(theme.colors), "color");
|
|
456
454
|
const textSizes = validateNames(Object.keys(theme.text), "text");
|
|
457
|
-
const breakpoints = validateNames(Object.keys(theme.breakpoints), "breakpoint");
|
|
458
455
|
const weightNames = validateNames(Object.keys(theme.weights), "weight");
|
|
459
|
-
const
|
|
460
|
-
|
|
461
|
-
|
|
456
|
+
const variantNames = literalSafe(variants.filter((v) => v.kind !== "pattern").map((v) => v.name));
|
|
457
|
+
const finiteClasses = literalSafe(enumeration.classes.map((c) => c.name));
|
|
458
|
+
const spacingRoots = validateNames(
|
|
459
|
+
enumeration.templates.filter((t) => t.kind === "spacing").map((t) => t.root),
|
|
460
|
+
"spacing root"
|
|
461
|
+
);
|
|
462
|
+
const numericRoots = validateNames(
|
|
463
|
+
enumeration.templates.filter((t) => t.kind === "number").map((t) => t.root),
|
|
464
|
+
"numeric root"
|
|
462
465
|
);
|
|
463
466
|
const functionalCustomUtilities = validateNames(
|
|
464
|
-
|
|
467
|
+
enumeration.templates.filter((t) => t.kind === "custom").map((t) => t.root),
|
|
465
468
|
"utility"
|
|
466
469
|
);
|
|
467
470
|
const union = (names) => names.length > 0 ? names.map((n) => `"${n}"`).join(" | ") : "never";
|
|
471
|
+
const unionLines = (names, perLine) => {
|
|
472
|
+
if (names.length === 0) return [" | never"];
|
|
473
|
+
const lines2 = [];
|
|
474
|
+
for (let i = 0; i < names.length; i += perLine) {
|
|
475
|
+
lines2.push(
|
|
476
|
+
` | ${names.slice(i, i + perLine).map((n) => `"${n}"`).join(" | ")}`
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
return lines2;
|
|
480
|
+
};
|
|
468
481
|
const lines = [
|
|
469
482
|
"// rainbowindex-env.d.ts (auto-generated \u2014 do not edit)",
|
|
470
483
|
"",
|
|
@@ -472,25 +485,44 @@ async function generateTypes(opts, cwd) {
|
|
|
472
485
|
`type ColorStop = "50" | "100" | "150" | "200" | "250" | "300" | "350" | "400" | "450" | "500" | "550" | "600" | "650" | "700" | "750" | "800" | "850" | "900" | "950";`,
|
|
473
486
|
"type SpacingToken = `${number}` | `${number}_${number}`;",
|
|
474
487
|
`type TextSize = ${union(textSizes)};`,
|
|
475
|
-
`type Variant = ${union(breakpoints)} | "hover" | "focus" | "focus-visible" | "active" | "disabled" | "dark" | "first" | "last" | "odd" | "even";`,
|
|
476
488
|
`type WeightName = ${union(weightNames)};`,
|
|
477
489
|
"",
|
|
478
|
-
"type
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
"
|
|
482
|
-
"
|
|
483
|
-
|
|
484
|
-
"
|
|
485
|
-
|
|
490
|
+
"type Variant =",
|
|
491
|
+
...unionLines(variantNames, 8),
|
|
492
|
+
" ;",
|
|
493
|
+
"",
|
|
494
|
+
"// Every finite class the compiler resolves for this theme \u2014 statics plus",
|
|
495
|
+
"// theme-token expansions, enumerated and probe-verified.",
|
|
496
|
+
"type RainbowStatic =",
|
|
497
|
+
...unionLines(finiteClasses, 6),
|
|
498
|
+
" ;"
|
|
486
499
|
];
|
|
487
|
-
if (
|
|
488
|
-
lines.push(`
|
|
500
|
+
if (spacingRoots.length > 0) {
|
|
501
|
+
lines.push("", `type SpacingRoot = ${union(spacingRoots)};`);
|
|
502
|
+
}
|
|
503
|
+
if (numericRoots.length > 0) {
|
|
504
|
+
lines.push(`type NumericRoot = ${union(numericRoots)};`);
|
|
505
|
+
}
|
|
506
|
+
lines.push("", "type RainbowBase =", " | RainbowStatic");
|
|
507
|
+
if (spacingRoots.length > 0) {
|
|
508
|
+
lines.push(" | `${SpacingRoot}-${SpacingToken}`");
|
|
509
|
+
}
|
|
510
|
+
if (numericRoots.length > 0) {
|
|
511
|
+
lines.push(" | `${NumericRoot}-${number}`");
|
|
489
512
|
}
|
|
490
513
|
if (functionalCustomUtilities.length > 0) {
|
|
491
514
|
lines.push(` | ${functionalCustomUtilities.map((n) => `\`${n}-\${string}\``).join(" | ")}`);
|
|
492
515
|
}
|
|
493
|
-
lines.push("
|
|
516
|
+
lines.push(" ;");
|
|
517
|
+
lines.push(
|
|
518
|
+
"",
|
|
519
|
+
"type RainbowClass =",
|
|
520
|
+
" | RainbowBase",
|
|
521
|
+
" // Variant-prefixed classes validate the variant name (chained prefixes",
|
|
522
|
+
" // match through the open remainder). Expanding Variant \xD7 RainbowBase",
|
|
523
|
+
" // eagerly would exceed TypeScript's union-size limits.",
|
|
524
|
+
" | `${Variant}:${string}`"
|
|
525
|
+
);
|
|
494
526
|
if (!opts.strict) {
|
|
495
527
|
lines.push(" | (string & {});");
|
|
496
528
|
} else {
|
|
@@ -1054,7 +1086,7 @@ async function resolveStylesheetPath(cwd, cssFile) {
|
|
|
1054
1086
|
if (cssFile) return resolve5(cwd, cssFile);
|
|
1055
1087
|
const importedCSS = await findImportedStylesheet(cwd);
|
|
1056
1088
|
if (importedCSS) return importedCSS;
|
|
1057
|
-
for (const candidate of
|
|
1089
|
+
for (const candidate of CSS_ENTRY_CANDIDATES) {
|
|
1058
1090
|
const fullPath = resolve5(cwd, candidate);
|
|
1059
1091
|
if (existsSync3(fullPath)) return fullPath;
|
|
1060
1092
|
}
|
|
@@ -1201,7 +1233,7 @@ function readPackageJSONSync(cwd) {
|
|
|
1201
1233
|
|
|
1202
1234
|
// src/entries/cli.ts
|
|
1203
1235
|
function getVersion() {
|
|
1204
|
-
return true ? "0.2.
|
|
1236
|
+
return true ? "0.2.2" : "unknown";
|
|
1205
1237
|
}
|
|
1206
1238
|
async function main() {
|
|
1207
1239
|
const args = process.argv.slice(2);
|
package/dist/editor.d.ts
ADDED
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
import { P as ParsedDirective, R as ResolvedTheme } from './index-DK6APAGD.js';
|
|
2
|
+
export { b as createThemeSnapshot } from './index-DK6APAGD.js';
|
|
3
|
+
import { C as ColorDefinition, b as CompilationSnapshot, M as MergeAnalysis } from './index-CfDtWufj.js';
|
|
4
|
+
export { n as MergeDrop, o as analyzeMerge, f as defaultTheme } from './index-CfDtWufj.js';
|
|
5
|
+
|
|
6
|
+
/** Helper-call names whose string arguments are walked for class literals.
|
|
7
|
+
* Exported for editor tooling so completion-context detection can match the
|
|
8
|
+
* scanner's own behavior. */
|
|
9
|
+
declare const CLASS_HELPER_NAMES: readonly string[];
|
|
10
|
+
/** Variant-config helper names (`cva`/`tv`) whose config objects are walked. */
|
|
11
|
+
declare const VARIANT_HELPER_NAMES: readonly string[];
|
|
12
|
+
interface SourceExtractionInput {
|
|
13
|
+
path?: string;
|
|
14
|
+
content: string;
|
|
15
|
+
}
|
|
16
|
+
type CandidateOrigin = "attribute" | "helper" | "safelist" | "plain";
|
|
17
|
+
interface ClassCandidate {
|
|
18
|
+
/** The class string in expanded form — for variant-group members this
|
|
19
|
+
* includes the group prefix (`hover:bg-red-500`) even though the span
|
|
20
|
+
* covers only the member token inside the braces. */
|
|
21
|
+
value: string;
|
|
22
|
+
/** Absolute [start, end) span of the visible token in the original source.
|
|
23
|
+
* `source.slice(start, end)` is the member token for group members and
|
|
24
|
+
* `value` itself everywhere else. */
|
|
25
|
+
start: number;
|
|
26
|
+
end: number;
|
|
27
|
+
origin: CandidateOrigin;
|
|
28
|
+
/** The call the class was found in, when origin is "helper"/"safelist". */
|
|
29
|
+
helperName?: string;
|
|
30
|
+
/** For variant-group members: span of the group's variant prefix (`hover:`). */
|
|
31
|
+
groupPrefix?: {
|
|
32
|
+
start: number;
|
|
33
|
+
end: number;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
declare function expandVariantGroups(input: string, warnings?: string[]): string;
|
|
37
|
+
declare function extractClasses(source: string, warnings?: string[]): Set<string>;
|
|
38
|
+
declare function extractClassesFromSource(input: SourceExtractionInput, warnings?: string[]): Set<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Position-aware variant of `extractClassesFromSource` for editor tooling.
|
|
41
|
+
* Same extractors, same filters, same pruning — the value set of the result
|
|
42
|
+
* always equals `extractClassesFromSource(input)`. Each candidate additionally
|
|
43
|
+
* carries its source span, its collection origin, and (for variant-group
|
|
44
|
+
* members) the group's prefix span. Candidates are sorted by position and
|
|
45
|
+
* deduped by span + value; a span found by both the whole-file scan and a
|
|
46
|
+
* context-aware collector reports the collector's origin.
|
|
47
|
+
*/
|
|
48
|
+
declare function extractClassCandidates(input: SourceExtractionInput, warnings?: string[]): ClassCandidate[];
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Lightweight source-file detection — no heavy dependencies (tinyglobby, etc.).
|
|
52
|
+
* Kept separate so the Vite integration can import it without pulling in
|
|
53
|
+
* Node-only glob machinery into browser bundles.
|
|
54
|
+
*/
|
|
55
|
+
declare function isSourceFile(file: string): boolean;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Default CSS entry candidates — the paths the CLI, the Vite plugin, and
|
|
59
|
+
* editor tooling probe (in order) when locating the project's Rainbow Index
|
|
60
|
+
* CSS input. Pure data, no filesystem access: IO-free consumers (editor
|
|
61
|
+
* tooling) reuse the exact detection order with their own file access and
|
|
62
|
+
* confirm a hit with `hasRIActivation()` on the file's contents.
|
|
63
|
+
*/
|
|
64
|
+
declare const CSS_ENTRY_CANDIDATES: readonly string[];
|
|
65
|
+
|
|
66
|
+
/** Import specifiers that activate RainbowIndex. Single source for the
|
|
67
|
+
* activation scan here, the PostCSS import matcher, and the strip regex. */
|
|
68
|
+
declare const RI_IMPORT_SPECIFIERS: readonly string[];
|
|
69
|
+
/**
|
|
70
|
+
* Detect whether source activates RainbowIndex: any RI directive token
|
|
71
|
+
* (including PostCSS-only `@apply` and `@slot`) or an `@import` of the
|
|
72
|
+
* package CSS, outside comments/strings. One fused scan covers both.
|
|
73
|
+
*/
|
|
74
|
+
declare function hasRIActivation(src: string): boolean;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Structured diagnostics — the typed view of the `[RI-NNNN] message` warning
|
|
78
|
+
* strings, for editor tooling that anchors problems to source spans.
|
|
79
|
+
*
|
|
80
|
+
* The legacy string arrays stay the wire format everywhere (and the warning
|
|
81
|
+
* budget/dedup in warnings.ts keeps operating on them); a Diagnostic carries
|
|
82
|
+
* the same full message text verbatim, plus the parsed code, a severity
|
|
83
|
+
* derived from the documented code-range convention, and — when the emission
|
|
84
|
+
* site knew one — a [start, end) span into the CSS input. Consumers can rely
|
|
85
|
+
* on `diagnostics[i].message === warnings[i]` wherever both are returned.
|
|
86
|
+
*/
|
|
87
|
+
type DiagnosticSeverity = "error" | "warning";
|
|
88
|
+
interface Diagnostic {
|
|
89
|
+
/** The RI-NNNN code, or null when the message carries no parseable code. */
|
|
90
|
+
code: string | null;
|
|
91
|
+
severity: DiagnosticSeverity;
|
|
92
|
+
/** The full legacy warning text, including the `[RI-NNNN]` prefix. */
|
|
93
|
+
message: string;
|
|
94
|
+
/** [start, end) span in the analyzed CSS input, or null when unknown. */
|
|
95
|
+
start: number | null;
|
|
96
|
+
end: number | null;
|
|
97
|
+
}
|
|
98
|
+
/** Extract the RI-NNNN code from a legacy warning string, or null. */
|
|
99
|
+
declare function warningCode(message: string): string | null;
|
|
100
|
+
/**
|
|
101
|
+
* Severity by code range — the same convention warnings.ts budgets by:
|
|
102
|
+
* RI-0xxx (fatal/bootstrap) and RI-2xxx (compile/runtime errors) are errors,
|
|
103
|
+
* everything else (informational 1xxx ranges) is a warning.
|
|
104
|
+
*/
|
|
105
|
+
declare function severityForCode(code: string | null): DiagnosticSeverity;
|
|
106
|
+
/** Wrap a legacy warning string as a Diagnostic, with an optional span. */
|
|
107
|
+
declare function diagnosticFromWarning(message: string, span?: readonly [number, number] | null): Diagnostic;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Theme-only project analysis — the cheap front half of compileProject.
|
|
111
|
+
*
|
|
112
|
+
* Kept in a leaf module (no assembly/font machinery in the import graph) so
|
|
113
|
+
* IO-free consumers — the `rainbowindex/editor` entry — can turn a CSS input
|
|
114
|
+
* string into a ResolvedTheme without dragging Node-only code along.
|
|
115
|
+
* `project/pipeline.ts` re-exports this module, so existing importers are
|
|
116
|
+
* unaffected.
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
interface ProjectAnalysis {
|
|
120
|
+
directives: ParsedDirective[];
|
|
121
|
+
theme: ResolvedTheme;
|
|
122
|
+
warnings: string[];
|
|
123
|
+
warningSeen: Set<string>;
|
|
124
|
+
/**
|
|
125
|
+
* Structured view of `warnings` — same messages, same order
|
|
126
|
+
* (`diagnostics[i].message === warnings[i]`), each with the parsed code,
|
|
127
|
+
* range-derived severity, and a [start, end) span into the CSS input when
|
|
128
|
+
* the emitter knew one: directive-parse problems point at the offending
|
|
129
|
+
* at-rule, resolver problems at the directive whose body produced them.
|
|
130
|
+
*/
|
|
131
|
+
diagnostics: Diagnostic[];
|
|
132
|
+
}
|
|
133
|
+
declare function analyzeProjectCSS(css: string): ProjectAnalysis;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Parses utility class strings into structured tokens.
|
|
137
|
+
*
|
|
138
|
+
* "hover:bg-red-500" → { variants: ["hover"], utility: "bg", value: "red-500" }
|
|
139
|
+
* "sm:p-4" → { variants: ["sm"], utility: "p", value: "4" }
|
|
140
|
+
* "text-center!" → { variants: [], utility: "text-center", value: null, important: true }
|
|
141
|
+
* "p-[13px]" → { variants: [], utility: "p", value: "[13px]", arbitrary: true }
|
|
142
|
+
* "@md:flex" → { variants: ["@md"], utility: "flex", value: null }
|
|
143
|
+
* "pl-physical-4" → { variants: [], utility: "pl", value: "4", physical: true }
|
|
144
|
+
*/
|
|
145
|
+
interface ParsedUtility {
|
|
146
|
+
/** Original class string before parsing */
|
|
147
|
+
raw: string;
|
|
148
|
+
/** Variant prefixes in order, e.g. ["hover"], ["sm", "hover"] */
|
|
149
|
+
variants: string[];
|
|
150
|
+
/** The utility name (everything before the value separator), e.g. "bg", "p", "text" */
|
|
151
|
+
utility: string;
|
|
152
|
+
/** The value part after the last `-`, or null for valueless utilities like "flex" */
|
|
153
|
+
value: string | null;
|
|
154
|
+
/** Whether the value is an arbitrary bracket expression like [13px] */
|
|
155
|
+
arbitrary: boolean;
|
|
156
|
+
/** Whether !important is applied */
|
|
157
|
+
important: boolean;
|
|
158
|
+
/** Whether the -physical- infix is present */
|
|
159
|
+
physical: boolean;
|
|
160
|
+
/** Whether the utility is negative (prefixed with -) */
|
|
161
|
+
negative: boolean;
|
|
162
|
+
/** When the class is an arbitrary property like [color:red] */
|
|
163
|
+
arbitraryProperty: {
|
|
164
|
+
property: string;
|
|
165
|
+
value: string;
|
|
166
|
+
} | null;
|
|
167
|
+
/**
|
|
168
|
+
* Explicit type hint extracted from an arbitrary value, e.g. the `length`
|
|
169
|
+
* in `border-[length:1rem]` or `border-(color:--my-color)`. When set, it
|
|
170
|
+
* forces a specific dispatch path in generators — see `borderGenerator`,
|
|
171
|
+
* `colorGenerator`, etc. Null when no hint was provided.
|
|
172
|
+
*/
|
|
173
|
+
dataType: string | null;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Parse a single utility class string into its structural components.
|
|
177
|
+
*/
|
|
178
|
+
declare function parseUtility(raw: string): ParsedUtility;
|
|
179
|
+
|
|
180
|
+
interface CSSDeclaration {
|
|
181
|
+
property: string;
|
|
182
|
+
value: string;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Variant resolution — maps variant names to CSS wrappers.
|
|
187
|
+
*
|
|
188
|
+
* Handles pseudo-classes, pseudo-elements, media queries, responsive breakpoints,
|
|
189
|
+
* container queries, data/aria attributes, :has()/:not(), arbitrary variants,
|
|
190
|
+
* and custom variants.
|
|
191
|
+
*/
|
|
192
|
+
|
|
193
|
+
type VariantKind = "pseudo-class" | "pseudo-element" | "media" | "breakpoint" | "container" | "special" | "custom" | "pattern";
|
|
194
|
+
interface VariantInfo {
|
|
195
|
+
/** The variant as typed before the `:` — for patterns, the family prefix. */
|
|
196
|
+
name: string;
|
|
197
|
+
kind: VariantKind;
|
|
198
|
+
/** What the variant emits — a selector suffix, an at-rule, or (for
|
|
199
|
+
* patterns) a description of the accepted form. */
|
|
200
|
+
wraps: string;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Enumerate every concrete variant the given theme resolves, plus the
|
|
204
|
+
* open-ended pattern families. Concrete entries (kind ≠ "pattern") are
|
|
205
|
+
* guaranteed to resolve via resolveVariant — the list mirrors its checks,
|
|
206
|
+
* including the CSS-length guard on breakpoint values.
|
|
207
|
+
*/
|
|
208
|
+
declare function listVariants(theme: ResolvedTheme): VariantInfo[];
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Class inspector — single-class validation and explanation for editor
|
|
212
|
+
* tooling, running the exact resolution the compile loop performs.
|
|
213
|
+
*
|
|
214
|
+
* The compiler intentionally drops unknown utilities silently (reserved
|
|
215
|
+
* RI-1001): the build scanner over-collects, so at build time an unresolved
|
|
216
|
+
* candidate is usually noise. Inside an editor the certainty is inverted — a
|
|
217
|
+
* token in a class attribute is meant to be a class — so the inspector
|
|
218
|
+
* finally gives RI-1001 a voice: `validate()` reports WHY a class produces no
|
|
219
|
+
* CSS, with a typo suggestion when one is close enough.
|
|
220
|
+
*
|
|
221
|
+
* An inspector instance owns the per-theme caches the compile loop rebuilds
|
|
222
|
+
* per pass (custom-variant map, variant memo, breakpoint weights) plus a
|
|
223
|
+
* resolution cache, so per-keystroke validation of the same classes is cheap.
|
|
224
|
+
* Create one per theme and drop it when the theme changes.
|
|
225
|
+
*/
|
|
226
|
+
|
|
227
|
+
type ClassValidation = {
|
|
228
|
+
ok: true;
|
|
229
|
+
} | {
|
|
230
|
+
ok: false;
|
|
231
|
+
reason: "unknown-utility" | "unknown-variant" | "invalid-arbitrary";
|
|
232
|
+
/** The failing fragment — the variant for "unknown-variant", the
|
|
233
|
+
* base class (variants stripped) otherwise. */
|
|
234
|
+
offender: string;
|
|
235
|
+
/** Closest known name within typo distance, when one exists. */
|
|
236
|
+
suggestion?: string;
|
|
237
|
+
};
|
|
238
|
+
interface ClassExplanation {
|
|
239
|
+
parsed: ParsedUtility;
|
|
240
|
+
/** Root declarations before variant wrapping. */
|
|
241
|
+
declarations: CSSDeclaration[];
|
|
242
|
+
/** Escaped selector, including variant suffixes (`.hover\:px-2:hover`). */
|
|
243
|
+
selector: string;
|
|
244
|
+
/** The complete rule text, including wrapping at-rules. */
|
|
245
|
+
css: string;
|
|
246
|
+
/** Deterministic ordering key — lower emits earlier in generated CSS. */
|
|
247
|
+
sortKey: number;
|
|
248
|
+
}
|
|
249
|
+
interface ClassInspector {
|
|
250
|
+
readonly theme: ResolvedTheme;
|
|
251
|
+
/** Would this class produce CSS under the theme? Reports why not. */
|
|
252
|
+
validate(className: string): ClassValidation;
|
|
253
|
+
/** Structured breakdown + generated CSS, or null when invalid. */
|
|
254
|
+
explain(className: string): ClassExplanation | null;
|
|
255
|
+
/** Every variant the theme resolves (cached). */
|
|
256
|
+
variants(): readonly VariantInfo[];
|
|
257
|
+
}
|
|
258
|
+
declare function createClassInspector(theme: ResolvedTheme): ClassInspector;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Typo suggestion helpers using optimal string alignment (OSA) distance —
|
|
262
|
+
* Levenshtein plus adjacent transpositions, so `felx` → `flex` is distance 1.
|
|
263
|
+
* Shared between engine.ts and css-functions.ts.
|
|
264
|
+
*/
|
|
265
|
+
/**
|
|
266
|
+
* Find the closest match to `input` from a list of candidates.
|
|
267
|
+
* Returns null if no candidate is within `maxDistance`.
|
|
268
|
+
*/
|
|
269
|
+
declare function findClosest(input: string, candidates: string[], maxDistance?: number): string | null;
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Class enumeration — the completion universe for editor tooling.
|
|
273
|
+
*
|
|
274
|
+
* Design: candidates are generated from a deliberately GENEROUS value-space
|
|
275
|
+
* table (which theme namespaces and keyword families to TRY per functional
|
|
276
|
+
* root), then every candidate is probed through the real utility resolver.
|
|
277
|
+
* The resolver is the single authority — an enumerated class is one that
|
|
278
|
+
* actually compiles, so the table can over-approximate freely and can never
|
|
279
|
+
* emit something `validate()` would reject. Coverage is enforced the other
|
|
280
|
+
* way by tests: every PREFIX_DISPATCH root must appear in the table (an empty
|
|
281
|
+
* spec marks a statics-only root), so adding a generator root without
|
|
282
|
+
* deciding its value space fails CI.
|
|
283
|
+
*
|
|
284
|
+
* Statics come from the merge conflict tables (STATIC_UTILITIES) plus each
|
|
285
|
+
* generator's own static-map keys — probed too, for the same guarantee.
|
|
286
|
+
*/
|
|
287
|
+
|
|
288
|
+
type ValueSpaceKind = "color" | "special-color" | "spacing" | "fraction" | "text-size" | "fluid-text-size" | "font-slot" | "weight" | "rounded" | "rounded-side" | "shadow" | "z" | "ease" | "blur" | "animation" | "leading" | "tracking" | "opacity" | "duration" | "breakpoint" | "int" | "percent" | "keywords";
|
|
289
|
+
interface ValueSpaceSpec {
|
|
290
|
+
kinds: readonly ValueSpaceKind[];
|
|
291
|
+
/** Extra value parts to try verbatim (for "keywords" and beyond). */
|
|
292
|
+
keywords?: readonly string[];
|
|
293
|
+
}
|
|
294
|
+
/** Root → value spaces to try. Coverage of every PREFIX_DISPATCH root is
|
|
295
|
+
* enforced by __tests__/core/enumerate.test.ts. */
|
|
296
|
+
declare const UTILITY_VALUE_SPACES: ReadonlyMap<string, ValueSpaceSpec>;
|
|
297
|
+
interface EnumeratedClass {
|
|
298
|
+
name: string;
|
|
299
|
+
/** How the class was produced: a static table, a custom @utility, or the
|
|
300
|
+
* value-space kind that filled the functional root. */
|
|
301
|
+
kind: ValueSpaceKind | "static" | "custom";
|
|
302
|
+
/** The functional root, or null for statics/custom statics. */
|
|
303
|
+
root: string | null;
|
|
304
|
+
}
|
|
305
|
+
interface ClassTemplate {
|
|
306
|
+
root: string;
|
|
307
|
+
/** The open-ended space: numeric spacing scale, plain numbers, or a
|
|
308
|
+
* functional custom utility that accepts any suffix. */
|
|
309
|
+
kind: "spacing" | "number" | "custom";
|
|
310
|
+
example: string;
|
|
311
|
+
}
|
|
312
|
+
interface ClassEnumeration {
|
|
313
|
+
/** Every finite concrete class, probed valid, sorted by name. */
|
|
314
|
+
classes: EnumeratedClass[];
|
|
315
|
+
/** Families whose value space is infinite — offer as snippets. */
|
|
316
|
+
templates: ClassTemplate[];
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Enumerate the finite completion universe for a theme. Every returned class
|
|
320
|
+
* has been resolved by the real utility resolver — `validate()` accepts each
|
|
321
|
+
* one by construction. Infinite families (the spacing scale, numeric values,
|
|
322
|
+
* functional custom utilities) come back as templates; a template is emitted
|
|
323
|
+
* only when at least one of its probes resolved.
|
|
324
|
+
*/
|
|
325
|
+
declare function enumerateClassNames(theme: ResolvedTheme): ClassEnumeration;
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Color swatches and theme-token introspection for editor tooling.
|
|
329
|
+
*
|
|
330
|
+
* Resolves a theme color (and stop) to concrete light/dark colors — the same
|
|
331
|
+
* OKLCH math the CSS variable emitter uses (generateStop / computeDarkStop),
|
|
332
|
+
* plus an sRGB hex conversion for completion-item swatches and sidebar chips.
|
|
333
|
+
* Pure computation, no IO.
|
|
334
|
+
*/
|
|
335
|
+
|
|
336
|
+
/** The canonical palette stops every generative color defines. */
|
|
337
|
+
declare const CANONICAL_COLOR_STOPS: readonly number[];
|
|
338
|
+
/** Convert an OKLCH color to a #rrggbb hex string (sRGB, channel-clamped). */
|
|
339
|
+
declare function oklchToHex(l: number, c: number, h: number): string;
|
|
340
|
+
/** Best-effort hex for the CSS color texts theme definitions hold: `oklch()`
|
|
341
|
+
* and hex literals. Anything else (named colors, rgb(), vars) returns null —
|
|
342
|
+
* the raw CSS text still travels alongside. */
|
|
343
|
+
declare function cssColorToHex(css: string): string | null;
|
|
344
|
+
interface SwatchColor {
|
|
345
|
+
/** CSS color text (`oklch(…)`, or the definition's own value verbatim). */
|
|
346
|
+
css: string;
|
|
347
|
+
/** sRGB hex, or null when the CSS text isn't convertible. */
|
|
348
|
+
hex: string | null;
|
|
349
|
+
}
|
|
350
|
+
interface ColorSwatch {
|
|
351
|
+
light: SwatchColor;
|
|
352
|
+
/** Null when the theme's dark mode is off or the color has no dark form. */
|
|
353
|
+
dark: SwatchColor | null;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Resolve a theme color name (+ stop, for generative palettes) to concrete
|
|
357
|
+
* light/dark swatch colors — exactly the values the emitted CSS variables
|
|
358
|
+
* carry. Theme-defined colors always win; the fixed semantic swatches
|
|
359
|
+
* (paper/ink/white/black) apply only when the theme does not define the name,
|
|
360
|
+
* mirroring the emitter (a user `@color { white: … }` palette emits
|
|
361
|
+
* `--color-white-*` variables that suffixed utilities resolve against).
|
|
362
|
+
* Returns null for unknown names, unresolvable aliases, and keyword colors
|
|
363
|
+
* with no concrete value (transparent, currentColor).
|
|
364
|
+
*/
|
|
365
|
+
declare function resolveColorSwatch(theme: ResolvedTheme, name: string, stop?: number): ColorSwatch | null;
|
|
366
|
+
interface ThemeTokens {
|
|
367
|
+
/** Color names with their definition kind — pair with resolveColorSwatch. */
|
|
368
|
+
colors: Array<{
|
|
369
|
+
name: string;
|
|
370
|
+
kind: ColorDefinition["type"];
|
|
371
|
+
}>;
|
|
372
|
+
colorStops: readonly number[];
|
|
373
|
+
spacingBase: string;
|
|
374
|
+
textSizes: Array<{
|
|
375
|
+
name: string;
|
|
376
|
+
fontSize: string;
|
|
377
|
+
lineHeight: string;
|
|
378
|
+
}>;
|
|
379
|
+
breakpoints: Record<string, string>;
|
|
380
|
+
rounded: Record<string, string>;
|
|
381
|
+
shadows: Record<string, string>;
|
|
382
|
+
weights: Record<string, number>;
|
|
383
|
+
easing: Record<string, string>;
|
|
384
|
+
blur: Record<string, string>;
|
|
385
|
+
z: Record<string, string>;
|
|
386
|
+
leading: Record<string, string>;
|
|
387
|
+
tracking: Record<string, string>;
|
|
388
|
+
opacity: Record<string, string>;
|
|
389
|
+
duration: Record<string, string>;
|
|
390
|
+
fonts: Array<{
|
|
391
|
+
slot: string;
|
|
392
|
+
family: string;
|
|
393
|
+
}>;
|
|
394
|
+
animations: string[];
|
|
395
|
+
}
|
|
396
|
+
/** One render-ready view of a theme's token namespaces for sidebar chips and
|
|
397
|
+
* completion detail — plain data, no theme internals to traverse. */
|
|
398
|
+
declare function listThemeTokens(theme: ResolvedTheme): ThemeTokens;
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Editor session — the façade that ties the editor toolkit together.
|
|
402
|
+
*
|
|
403
|
+
* An editor host holds one session per workspace, calls `setCss()` whenever
|
|
404
|
+
* the project's CSS entry changes, and everything else per keystroke. The
|
|
405
|
+
* session owns the caching story: theme analysis, the class inspector, the
|
|
406
|
+
* enumeration, token introspection, and the merge snapshot are computed
|
|
407
|
+
* lazily and invalidated together when the CSS changes — callers never
|
|
408
|
+
* juggle per-theme cache keys themselves. Every capability is also exported
|
|
409
|
+
* à la carte from `rainbowindex/editor` for hosts that want finer control.
|
|
410
|
+
*
|
|
411
|
+
* Pure computation, no IO: the host reads the CSS file (see
|
|
412
|
+
* CSS_ENTRY_CANDIDATES / hasRIActivation for locating it) and passes text.
|
|
413
|
+
*/
|
|
414
|
+
|
|
415
|
+
interface EditorSession {
|
|
416
|
+
/** The CSS input the session is currently analyzing. */
|
|
417
|
+
readonly css: string;
|
|
418
|
+
/** Swap the CSS input; all theme-derived caches invalidate together.
|
|
419
|
+
* A no-op when the text is unchanged. */
|
|
420
|
+
setCss(css: string): void;
|
|
421
|
+
readonly theme: ResolvedTheme;
|
|
422
|
+
/** Positioned diagnostics for the CSS input (see ProjectAnalysis). */
|
|
423
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
424
|
+
/** Single-class validation/explanation, cached per theme. */
|
|
425
|
+
readonly inspector: ClassInspector;
|
|
426
|
+
/** The finite completion universe + templates, cached per theme. */
|
|
427
|
+
enumerate(): ClassEnumeration;
|
|
428
|
+
/** Render-ready token namespaces, cached per theme. */
|
|
429
|
+
tokens(): ThemeTokens;
|
|
430
|
+
/** The merge snapshot for this theme, cached. */
|
|
431
|
+
snapshot(): CompilationSnapshot;
|
|
432
|
+
/** analyzeMerge bound to this theme's snapshot. */
|
|
433
|
+
analyzeMerge(classes: readonly string[]): MergeAnalysis;
|
|
434
|
+
/** Position-aware class extraction for a source document. */
|
|
435
|
+
extractCandidates(content: string, path?: string): ClassCandidate[];
|
|
436
|
+
/** Light/dark swatch for a theme color (+ stop), or null. */
|
|
437
|
+
swatch(name: string, stop?: number): ColorSwatch | null;
|
|
438
|
+
}
|
|
439
|
+
declare function createEditorSession(options?: {
|
|
440
|
+
css?: string;
|
|
441
|
+
}): EditorSession;
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* `rainbowindex/editor` — the IO-free toolkit editor integrations build on.
|
|
445
|
+
*
|
|
446
|
+
* Everything exported here is pure computation: strings in, structures out.
|
|
447
|
+
* No filesystem, no network, no module-level mutation — the entry behaves in
|
|
448
|
+
* browser-based editor hosts (vscode.dev) exactly as it does in Node. File
|
|
449
|
+
* access stays with the editor host; this module supplies the semantics:
|
|
450
|
+
* what the scanner extracts (and where), what activates Rainbow Index, and
|
|
451
|
+
* where a project's CSS entry usually lives.
|
|
452
|
+
*
|
|
453
|
+
* Editor integrations load whatever version the workspace has installed, so
|
|
454
|
+
* the surface is feature-detectable: gate on `editorCapabilities` entries,
|
|
455
|
+
* not on `version`, when deciding what the installed copy supports.
|
|
456
|
+
*/
|
|
457
|
+
/** Package version — build-time injected; "0.0.0-dev" when run from source. */
|
|
458
|
+
declare const version: string;
|
|
459
|
+
/** Editor API protocol version — bumped only on breaking changes to this entry. */
|
|
460
|
+
declare const EDITOR_API_VERSION = 1;
|
|
461
|
+
/** Feature-detection roster for this entry. */
|
|
462
|
+
declare const editorCapabilities: readonly string[];
|
|
463
|
+
|
|
464
|
+
export { CANONICAL_COLOR_STOPS, CLASS_HELPER_NAMES, CSS_ENTRY_CANDIDATES, type CandidateOrigin, type ClassCandidate, type ClassEnumeration, type ClassExplanation, type ClassInspector, type ClassTemplate, type ClassValidation, ColorDefinition, type ColorSwatch, CompilationSnapshot, type Diagnostic, type DiagnosticSeverity, EDITOR_API_VERSION, type EditorSession, type EnumeratedClass, MergeAnalysis, ParsedDirective, type ParsedUtility, type ProjectAnalysis, RI_IMPORT_SPECIFIERS, ResolvedTheme, type SourceExtractionInput, type SwatchColor, type ThemeTokens, UTILITY_VALUE_SPACES, VARIANT_HELPER_NAMES, type ValueSpaceKind, type ValueSpaceSpec, type VariantInfo, type VariantKind, analyzeProjectCSS, createClassInspector, createEditorSession, cssColorToHex, diagnosticFromWarning, editorCapabilities, enumerateClassNames, expandVariantGroups, extractClassCandidates, extractClasses, extractClassesFromSource, findClosest, hasRIActivation, isSourceFile, listThemeTokens, listVariants, oklchToHex, parseUtility, resolveColorSwatch, severityForCode, version, warningCode };
|