rainbowindex 0.5.1 → 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.
@@ -5,7 +5,7 @@ import {
5
5
  RI_IMPORT_SPECIFIER_ALTERNATION,
6
6
  SAFE_FONT_FAMILY_RE,
7
7
  SHADOW_VAR_REF_RE,
8
- analyzeProjectCSS,
8
+ analyzeProjectCSSMemo,
9
9
  codepointCompare,
10
10
  compileCSSFunctions,
11
11
  createCompiler,
@@ -19,12 +19,12 @@ import {
19
19
  renderCSS,
20
20
  scanCSSForTokenUsage,
21
21
  withTimeout
22
- } from "./chunk-PDORZSQX.mjs";
22
+ } from "./chunk-KSNYSR3C.mjs";
23
23
  import {
24
24
  checkPaletteContrast,
25
25
  generateAllColorVariables,
26
26
  generateThemeOverrides
27
- } from "./chunk-4UKFK2GE.mjs";
27
+ } from "./chunk-6U4IOFOS.mjs";
28
28
 
29
29
  // src/scanner/sources.ts
30
30
  import { readFile, stat } from "fs/promises";
@@ -305,8 +305,37 @@ function collectInlineClasses(sources) {
305
305
  var FILE_IO_TIMEOUT_MS = 1e4;
306
306
  var SCAN_CACHE_MAX_ENTRIES = 2e4;
307
307
  var scanCache = /* @__PURE__ */ new Map();
308
+ var scanChangeTrackingEnabled = false;
309
+ function enableScanChangeTracking() {
310
+ scanChangeTrackingEnabled = true;
311
+ }
312
+ function markSourceFileChanged(file, cwd) {
313
+ scanCache.delete(cwd === void 0 ? file : resolve2(cwd, file));
314
+ }
315
+ function disableScanChangeTracking() {
316
+ scanChangeTrackingEnabled = false;
317
+ scanCache.clear();
318
+ }
319
+ var fileUnion = null;
320
+ function applyToUnion(union, result, delta) {
321
+ if (!result?.classes) return;
322
+ for (const cls of result.classes) {
323
+ const next = (union.counts.get(cls) ?? 0) + delta;
324
+ if (next > 0) {
325
+ union.counts.set(cls, next);
326
+ if (delta === 1) union.classes.add(cls);
327
+ } else {
328
+ union.counts.delete(cls);
329
+ union.classes.delete(cls);
330
+ }
331
+ }
332
+ }
308
333
  async function scanOneFile(file) {
309
334
  const warnings = [];
335
+ if (scanChangeTrackingEnabled) {
336
+ const tracked = scanCache.get(file);
337
+ if (tracked) return tracked.result;
338
+ }
310
339
  try {
311
340
  const stats = await withTimeout(stat(file), FILE_IO_TIMEOUT_MS, "stat() timed out");
312
341
  const cached = scanCache.get(file);
@@ -370,21 +399,29 @@ async function scanSourceFilesAsync(sources, cwd) {
370
399
  seen.add(result.failure);
371
400
  continue;
372
401
  }
373
- if (result.classes) {
374
- for (const cls of result.classes) {
375
- allClasses.add(cls);
376
- }
377
- }
378
402
  pushWarningsDeduped(allWarnings, result.warnings, seen);
379
403
  }
404
+ if (fileUnion === null || fileUnion.results.length !== results.length) {
405
+ fileUnion = { results, counts: /* @__PURE__ */ new Map(), classes: /* @__PURE__ */ new Set() };
406
+ for (const result of results) applyToUnion(fileUnion, result, 1);
407
+ } else {
408
+ const previous = fileUnion.results;
409
+ for (let i = 0; i < results.length; i++) {
410
+ if (previous[i] === results[i]) continue;
411
+ applyToUnion(fileUnion, previous[i], -1);
412
+ applyToUnion(fileUnion, results[i], 1);
413
+ }
414
+ fileUnion.results = results;
415
+ }
416
+ for (const cls of fileUnion.classes) allClasses.add(cls);
380
417
  return { classes: allClasses, authored, warnings: allWarnings };
381
418
  }
382
- async function collectProjectClasses(themeSources, surfaceSources, cwd, warnings, warningSeen) {
419
+ async function collectProjectClasses(themeSources, surfaceSources, cwd, warnings, warningSeen, suppressed) {
383
420
  const discovered = discoverPackageSafelistSources(cwd);
384
- pushWarningsDeduped(warnings, discovered.warnings, warningSeen);
421
+ pushWarningsDeduped(warnings, discovered.warnings, warningSeen, suppressed);
385
422
  const allSources = [...themeSources, ...surfaceSources, ...discovered.sources];
386
423
  const scanResult = await scanSourceFilesAsync(allSources, cwd);
387
- pushWarningsDeduped(warnings, scanResult.warnings, warningSeen);
424
+ pushWarningsDeduped(warnings, scanResult.warnings, warningSeen, suppressed);
388
425
  return { classes: scanResult.classes, authored: scanResult.authored };
389
426
  }
390
427
 
@@ -1457,15 +1494,15 @@ ${m.css}`).join("\n\n");
1457
1494
  function generateTokenLayer(theme, usage, fontOutputCache) {
1458
1495
  const vars = [];
1459
1496
  vars.push(`--spacing: ${theme.spacing.base};`);
1460
- vars.push(`--fluid-min: ${theme.fluid.min};`);
1461
- vars.push(`--fluid-max: ${theme.fluid.max};`);
1462
- if (theme.textFluid) {
1463
- vars.push(`--fluid-text-min: ${theme.textFluid.min};`);
1464
- vars.push(`--fluid-text-max: ${theme.textFluid.max};`);
1465
- }
1466
- if (theme.spacingFluid) {
1467
- vars.push(`--fluid-spacing-min: ${theme.spacingFluid.min};`);
1468
- vars.push(`--fluid-spacing-max: ${theme.spacingFluid.max};`);
1497
+ const pushBounds = (prefix, config) => {
1498
+ if (config?.min !== void 0) vars.push(`${prefix}-min: ${config.min};`);
1499
+ if (config?.max !== void 0) vars.push(`${prefix}-max: ${config.max};`);
1500
+ };
1501
+ pushBounds("--fluid", theme.fluid);
1502
+ pushBounds("--fluid-text", theme.textFluid);
1503
+ pushBounds("--fluid-spacing", theme.spacingFluid);
1504
+ for (const [name, range] of Object.entries(theme.fluidRanges)) {
1505
+ pushBounds(`--fluid-${name}`, range);
1469
1506
  }
1470
1507
  const effectiveStops = new Map(
1471
1508
  [...usage.usedColorStops].map(([k, v]) => [k, new Set(v)])
@@ -1538,6 +1575,11 @@ function generateTokenLayer(theme, usage, fontOutputCache) {
1538
1575
  if (!shadowsToEmit.has(name)) continue;
1539
1576
  vars.push(`--shadow-${name}: ${val};`);
1540
1577
  }
1578
+ for (const [name, val] of Object.entries(theme.radii).sort(
1579
+ ([a], [b]) => codepointCompare(a, b)
1580
+ )) {
1581
+ vars.push(`--rounded-${name}: ${val};`);
1582
+ }
1541
1583
  for (const [name, def] of Object.entries(theme.animations).sort(
1542
1584
  ([a], [b]) => codepointCompare(a, b)
1543
1585
  )) {
@@ -1737,10 +1779,10 @@ function applyLayerWrapping(parts, layer) {
1737
1779
  }
1738
1780
 
1739
1781
  // src/project/pipeline.ts
1740
- function collectApplyClassNames(css, warnings) {
1782
+ function collectApplyClassNames(css, warnings, cssPath) {
1741
1783
  const classes = [];
1742
1784
  for (const match of css.matchAll(APPLY_LIKE_MATCH_RE)) {
1743
- const params = expandVariantGroups(match[1], warnings);
1785
+ const params = expandVariantGroups(match[1], warnings, cssPath);
1744
1786
  for (const className of params.trim().split(/\s+/)) {
1745
1787
  if (className) classes.push(className);
1746
1788
  }
@@ -1766,12 +1808,17 @@ async function finalizeProjectCompilation(options) {
1766
1808
  const expansionWarnings = [];
1767
1809
  const classNameSet = new Set(options.classNames);
1768
1810
  const authored = options.authoredClassNames && new Set(options.authoredClassNames);
1769
- for (const cls of collectApplyClassNames(options.css, expansionWarnings)) {
1811
+ for (const cls of collectApplyClassNames(options.css, expansionWarnings, options.cssPath)) {
1770
1812
  classNameSet.add(cls);
1771
1813
  authored?.add(cls);
1772
1814
  }
1773
1815
  const classNames = [...classNameSet];
1774
- pushWarningsDeduped(analysis.warnings, expansionWarnings, analysis.warningSeen);
1816
+ pushWarningsDeduped(
1817
+ analysis.warnings,
1818
+ expansionWarnings,
1819
+ analysis.warningSeen,
1820
+ analysis.suppressed
1821
+ );
1775
1822
  const compiler = createCompiler();
1776
1823
  const compilation = compiler.compile(classNames, effectiveTheme, authored);
1777
1824
  let userCSS = stripRIDirectives(options.css);
@@ -1786,8 +1833,18 @@ async function finalizeProjectCompilation(options) {
1786
1833
  effectiveTheme,
1787
1834
  compiler.fontOutputCache
1788
1835
  );
1789
- pushWarningsDeduped(analysis.warnings, assemblyWarnings, analysis.warningSeen);
1790
- pushWarningsDeduped(analysis.warnings, compilation.warnings, analysis.warningSeen);
1836
+ pushWarningsDeduped(
1837
+ analysis.warnings,
1838
+ assemblyWarnings,
1839
+ analysis.warningSeen,
1840
+ analysis.suppressed
1841
+ );
1842
+ pushWarningsDeduped(
1843
+ analysis.warnings,
1844
+ compilation.warnings,
1845
+ analysis.warningSeen,
1846
+ analysis.suppressed
1847
+ );
1791
1848
  let joinedCSS = null;
1792
1849
  return {
1793
1850
  get css() {
@@ -1801,24 +1858,12 @@ async function finalizeProjectCompilation(options) {
1801
1858
  classNames,
1802
1859
  theme: effectiveTheme,
1803
1860
  directives: analysis.directives,
1804
- warnings: analysis.warnings
1861
+ warnings: analysis.warnings,
1862
+ suppressed: analysis.suppressed
1805
1863
  };
1806
1864
  }
1807
1865
 
1808
1866
  // src/project/scan.ts
1809
- var lastAnalysis = null;
1810
- function analyzeProjectCSSMemo(css) {
1811
- if (lastAnalysis === null || lastAnalysis.css !== css) {
1812
- lastAnalysis = { css, analysis: analyzeProjectCSS(css) };
1813
- }
1814
- const cached = lastAnalysis.analysis;
1815
- return {
1816
- ...cached,
1817
- warnings: [...cached.warnings],
1818
- warningSeen: new Set(cached.warningSeen),
1819
- diagnostics: [...cached.diagnostics]
1820
- };
1821
- }
1822
1867
  async function compileScannedProject(options) {
1823
1868
  const analysis = analyzeProjectCSSMemo(options.css);
1824
1869
  const resolveFonts = options.resolveFonts ?? resolveGoogleFonts;
@@ -1831,7 +1876,12 @@ async function compileScannedProject(options) {
1831
1876
  if (error) {
1832
1877
  const warning = options.onInvalidPattern(error);
1833
1878
  if (warning !== void 0) {
1834
- pushWarningsDeduped(analysis.warnings, [warning], analysis.warningSeen);
1879
+ pushWarningsDeduped(
1880
+ analysis.warnings,
1881
+ [warning],
1882
+ analysis.warningSeen,
1883
+ analysis.suppressed
1884
+ );
1835
1885
  }
1836
1886
  continue;
1837
1887
  }
@@ -1842,10 +1892,12 @@ async function compileScannedProject(options) {
1842
1892
  surfaceSources,
1843
1893
  options.cwd,
1844
1894
  analysis.warnings,
1845
- analysis.warningSeen
1895
+ analysis.warningSeen,
1896
+ analysis.suppressed
1846
1897
  );
1847
1898
  const compiled = await finalizeProjectCompilation({
1848
1899
  css: options.css,
1900
+ cssPath: options.cssPath,
1849
1901
  classNames,
1850
1902
  authoredClassNames: authored,
1851
1903
  analysis,
@@ -1861,6 +1913,9 @@ export {
1861
1913
  DEFAULT_EXCLUDES,
1862
1914
  enableSourceFileListCache,
1863
1915
  invalidateSourceFileListCache,
1916
+ enableScanChangeTracking,
1917
+ markSourceFileChanged,
1918
+ disableScanChangeTracking,
1864
1919
  finalizeProjectCompilation,
1865
1920
  compileScannedProject
1866
1921
  };
@@ -15,10 +15,10 @@ import {
15
15
  codepointCompare,
16
16
  parseUtility,
17
17
  resolveUtilityDeclarations
18
- } from "./chunk-PDORZSQX.mjs";
18
+ } from "./chunk-KSNYSR3C.mjs";
19
19
  import {
20
20
  SPECIAL_COLORS
21
- } from "./chunk-4UKFK2GE.mjs";
21
+ } from "./chunk-6U4IOFOS.mjs";
22
22
 
23
23
  // src/project/css-entry.ts
24
24
  var CSS_ENTRY_CANDIDATES = Object.freeze([
@@ -70,6 +70,8 @@ var FRACTION_SAMPLES = Object.freeze([
70
70
  "5/6"
71
71
  ]);
72
72
  var INT_SAMPLES = Object.freeze(["0", "1", "2", "3", "4", "6", "8", "10", "12"]);
73
+ var INT_RE = /^\d+$/;
74
+ var WEIGHT_STEPS = Object.freeze(["100", "200", "300", "400", "500", "600", "700", "800", "900"]);
73
75
  var PERCENT_SAMPLES = Object.freeze([
74
76
  "0",
75
77
  "5",
@@ -137,16 +139,22 @@ function candidateValues(kind, theme) {
137
139
  return Object.keys(theme.text);
138
140
  case "fluid-text-size":
139
141
  return Object.keys(theme.text).map((size) => `fluid-${size}`);
142
+ case "fluid-range":
143
+ return Object.keys(theme.fluidRanges);
140
144
  case "font-slot":
141
145
  return [.../* @__PURE__ */ new Set([...BUILTIN_FONT_SLOTS, ...theme.fonts.map((slot) => slot.slot)])];
142
146
  case "weight":
143
- return Object.keys(theme.weights);
147
+ return [...Object.keys(theme.weights), ...WEIGHT_STEPS];
148
+ // Named @rounded radii plus the spacing multiples, the way @weight pairs
149
+ // its tokens with the numeric steps. Without the names, `rounded-roof`
150
+ // compiles but is offered by neither completions nor generated types.
144
151
  case "rounded":
145
- return [...RADIUS_SAMPLES];
152
+ return [...Object.keys(theme.radii), ...RADIUS_SAMPLES];
146
153
  case "rounded-side": {
147
154
  const out = [];
155
+ const sizes = [...Object.keys(theme.radii), ...RADIUS_SAMPLES];
148
156
  for (const side of ROUNDED_SIDES) {
149
- for (const size of RADIUS_SAMPLES) out.push(`${side}-${size}`);
157
+ for (const size of sizes) out.push(`${side}-${size}`);
150
158
  }
151
159
  return out;
152
160
  }
@@ -222,7 +230,7 @@ function enumerateClassNames(theme) {
222
230
  seen.add(name);
223
231
  classes.push({ name, kind, root });
224
232
  if (kind === "spacing") spacingHit = true;
225
- if (kind === "int") intHit = true;
233
+ if (kind === "int" || kind === "weight" && INT_RE.test(value)) intHit = true;
226
234
  }
227
235
  }
228
236
  for (const keyword of spec.keywords ?? []) {
package/dist/cli.mjs CHANGED
@@ -2,13 +2,18 @@
2
2
  import {
3
3
  CSS_ENTRY_CANDIDATES,
4
4
  enumerateClassNames
5
- } from "./chunk-RU4756NG.mjs";
5
+ } from "./chunk-ZR7XJMUN.mjs";
6
6
  import {
7
7
  DEFAULT_EXCLUDES,
8
8
  DEFAULT_PATTERNS,
9
9
  compileScannedProject,
10
- getFontPreloadLinks
11
- } from "./chunk-F4VCBISU.mjs";
10
+ disableScanChangeTracking,
11
+ enableScanChangeTracking,
12
+ enableSourceFileListCache,
13
+ getFontPreloadLinks,
14
+ invalidateSourceFileListCache,
15
+ markSourceFileChanged
16
+ } from "./chunk-WK6S4HTC.mjs";
12
17
  import {
13
18
  MAX_DIRECTIVE_INPUT_SIZE,
14
19
  codepointCompare,
@@ -18,10 +23,10 @@ import {
18
23
  hasRIActivation,
19
24
  listVariants,
20
25
  resolveDirectives
21
- } from "./chunk-PDORZSQX.mjs";
26
+ } from "./chunk-KSNYSR3C.mjs";
22
27
  import {
23
28
  devWarn
24
- } from "./chunk-4UKFK2GE.mjs";
29
+ } from "./chunk-6U4IOFOS.mjs";
25
30
 
26
31
  // src/entries/cli.ts
27
32
  import { realpathSync } from "fs";
@@ -434,6 +439,7 @@ async function buildCSS(opts, cwd) {
434
439
  const { css: cssSource, cssFile } = await loadProjectCSS(opts, cwd);
435
440
  const { compiled } = await compileScannedProject({
436
441
  css: cssSource,
442
+ cssPath: cssFile ?? void 0,
437
443
  cwd,
438
444
  surfacePatterns: opts.globs,
439
445
  onInvalidPattern: (err) => {
@@ -765,9 +771,23 @@ async function watchMode(opts, cwd) {
765
771
  currentBuild = runBuild();
766
772
  }, delay);
767
773
  };
768
- watcher.on("change", scheduleRebuild);
769
- watcher.on("add", scheduleRebuild);
770
- watcher.on("unlink", scheduleRebuild);
774
+ enableSourceFileListCache();
775
+ enableScanChangeTracking();
776
+ watcher.on("change", (file) => {
777
+ markSourceFileChanged(file, cwd);
778
+ scheduleRebuild();
779
+ });
780
+ watcher.on("add", (file) => {
781
+ invalidateSourceFileListCache();
782
+ markSourceFileChanged(file, cwd);
783
+ scheduleRebuild();
784
+ });
785
+ watcher.on("unlink", (file) => {
786
+ invalidateSourceFileListCache();
787
+ markSourceFileChanged(file, cwd);
788
+ scheduleRebuild();
789
+ });
790
+ watcher.on("unlinkDir", invalidateSourceFileListCache);
771
791
  watcher.on("error", (err) => {
772
792
  console.error("[rainbowindex] Watcher error:", err);
773
793
  });
@@ -777,6 +797,8 @@ async function watchMode(opts, cwd) {
777
797
  cleanupCalled = true;
778
798
  if (debounceTimer) clearTimeout(debounceTimer);
779
799
  dirty = false;
800
+ invalidateSourceFileListCache();
801
+ disableScanChangeTracking();
780
802
  const doExit = () => {
781
803
  watcher.close().then(() => {
782
804
  console.log("\n[rainbowindex] Watcher stopped.");
@@ -1289,7 +1311,7 @@ function readPackageJSONSync(cwd) {
1289
1311
 
1290
1312
  // src/entries/cli.ts
1291
1313
  function getVersion() {
1292
- return true ? "0.5.1" : "unknown";
1314
+ return true ? "0.6.0" : "unknown";
1293
1315
  }
1294
1316
  async function main() {
1295
1317
  const args = process.argv.slice(2);
package/dist/editor.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { P as ParsedDirective, R as ResolvedTheme } from './index-Dx-NpFFx.js';
2
- export { b as createThemeSnapshot } from './index-Dx-NpFFx.js';
3
- import { b as CompilationSnapshot, C as ColorDefinition } from './context-B9yhJxd5.js';
4
- export { e as defaultTheme } from './context-B9yhJxd5.js';
1
+ import { P as ParsedDirective, R as ResolvedTheme } from './index-4Kyaq3IZ.js';
2
+ export { b as createThemeSnapshot, d as describeLoadedWeights, w as weightIsLoaded } from './index-4Kyaq3IZ.js';
3
+ import { b as CompilationSnapshot, C as ColorDefinition } from './index-DSgpB6bS.js';
4
+ export { e as defaultTheme } from './index-DSgpB6bS.js';
5
5
 
6
6
  /** Where a candidate was found. "expression" marks a string literal sitting
7
7
  * in a JS expression position that cannot be a class list — today, an
@@ -44,7 +44,7 @@ declare const CLASS_HELPER_NAMES: readonly string[];
44
44
  declare const VARIANT_HELPER_NAMES: readonly string[];
45
45
  declare function extractClasses(source: string, warnings?: string[]): Set<string>;
46
46
 
47
- declare function expandVariantGroups(input: string, warnings?: string[]): string;
47
+ declare function expandVariantGroups(input: string, warnings?: string[], path?: string): string;
48
48
 
49
49
  interface SourceExtractionInput {
50
50
  path?: string;
@@ -144,9 +144,23 @@ interface ProjectAnalysis {
144
144
  * at-rule, resolver problems at the directive whose body produced them.
145
145
  */
146
146
  diagnostics: Diagnostic[];
147
+ /**
148
+ * Codes silenced for the whole entry by `/* ri-disable … *\/`. Later stages
149
+ * push through this so a code the author hid never reaches the caller —
150
+ * scanner and compile warnings included, which no stylesheet comment could
151
+ * reach by position.
152
+ */
153
+ suppressed: ReadonlySet<string>;
147
154
  }
148
155
  declare function analyzeProjectCSS(css: string): ProjectAnalysis;
149
156
 
157
+ /**
158
+ * Fatal bootstrap (RI-00xx) and runtime (RI-20xx) codes are never silenceable.
159
+ * They report a broken build or a broken call, not a style choice, and a
160
+ * stylesheet that could hide them would hide the reason the build failed.
161
+ */
162
+ declare function isSuppressible(code: string): boolean;
163
+
150
164
  /**
151
165
  * Parses utility class strings into structured tokens.
152
166
  *
@@ -309,7 +323,7 @@ declare function findClosest(input: string, candidates: string[], maxDistance?:
309
323
  * per-root resolver order fixes which generator wins a contested root.
310
324
  */
311
325
 
312
- 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";
326
+ type ValueSpaceKind = "color" | "special-color" | "spacing" | "fraction" | "text-size" | "fluid-text-size" | "font-slot" | "weight" | "rounded" | "rounded-side" | "shadow" | "z" | "ease" | "blur" | "animation" | "leading" | "fluid-range" | "tracking" | "opacity" | "duration" | "breakpoint" | "int" | "percent" | "keywords";
313
327
  interface ValueSpaceSpec {
314
328
  kinds: readonly ValueSpaceKind[];
315
329
  /** Extra value parts to try verbatim (for "keywords" and beyond). */
@@ -468,6 +482,15 @@ interface ThemeTokens {
468
482
  tracking: Record<string, string>;
469
483
  opacity: Record<string, string>;
470
484
  duration: Record<string, string>;
485
+ /** Named radii from `@rounded { roof: 24px; }` — the class is `rounded-roof`.
486
+ * Unnamed radii are spacing multiples and carry no token. */
487
+ radii: Record<string, string>;
488
+ /** Named ranges from `@fluid <name> { min; max; }` — each one makes the scope
489
+ * class `fluid-<name>`. A bound absent from the block is absent here. */
490
+ fluidRanges: Record<string, {
491
+ min?: string;
492
+ max?: string;
493
+ }>;
471
494
  fonts: Array<{
472
495
  slot: string;
473
496
  family: string;
@@ -542,4 +565,4 @@ declare const EDITOR_API_VERSION = 1;
542
565
  /** Feature-detection roster for this entry. */
543
566
  declare const editorCapabilities: readonly string[];
544
567
 
545
- 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, type MergeAnalysis, type MergeDrop, 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, analyzeMerge, analyzeProjectCSS, createClassInspector, createEditorSession, cssColorToHex, diagnosticFromWarning, editorCapabilities, enumerateClassNames, expandVariantGroups, extractClassCandidates, extractClasses, extractClassesFromSource, findClosest, hasRIActivation, isSourceFile, listThemeTokens, listVariants, oklchToHex, parseUtility, resolveColorSwatch, severityForCode, version, warningCode };
568
+ 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, type MergeAnalysis, type MergeDrop, 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, analyzeMerge, analyzeProjectCSS, createClassInspector, createEditorSession, cssColorToHex, diagnosticFromWarning, editorCapabilities, enumerateClassNames, expandVariantGroups, extractClassCandidates, extractClasses, extractClassesFromSource, findClosest, hasRIActivation, isSourceFile, isSuppressible, listThemeTokens, listVariants, oklchToHex, parseUtility, resolveColorSwatch, severityForCode, version, warningCode };
package/dist/editor.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  CSS_ENTRY_CANDIDATES,
3
3
  UTILITY_VALUE_SPACES,
4
4
  enumerateClassNames
5
- } from "./chunk-RU4756NG.mjs";
5
+ } from "./chunk-ZR7XJMUN.mjs";
6
6
  import {
7
7
  isSourceFile
8
8
  } from "./chunk-3HRMFZGE.mjs";
@@ -16,6 +16,7 @@ import {
16
16
  compileUtility,
17
17
  createEmptyCompilationResult,
18
18
  createThemeSnapshot,
19
+ describeLoadedWeights,
19
20
  diagnosticFromWarning,
20
21
  expandVariantGroups,
21
22
  extractClassCandidates,
@@ -23,11 +24,13 @@ import {
23
24
  extractClassesFromSource,
24
25
  findClosest,
25
26
  hasRIActivation,
27
+ isSuppressible,
26
28
  listVariants,
27
29
  parseUtility,
28
30
  severityForCode,
29
- warningCode
30
- } from "./chunk-PDORZSQX.mjs";
31
+ warningCode,
32
+ weightIsLoaded
33
+ } from "./chunk-KSNYSR3C.mjs";
31
34
  import {
32
35
  computeDarkStop,
33
36
  defaultTheme,
@@ -38,7 +41,7 @@ import {
38
41
  oklabToLinearSrgb,
39
42
  oklchToOklab,
40
43
  resolverFor
41
- } from "./chunk-4UKFK2GE.mjs";
44
+ } from "./chunk-6U4IOFOS.mjs";
42
45
 
43
46
  // src/engine/inspector.ts
44
47
  var RESOLUTION_CACHE_CAP = 1e4;
@@ -316,6 +319,13 @@ function listThemeTokens(theme) {
316
319
  tracking: { ...theme.tracking },
317
320
  opacity: { ...theme.opacity },
318
321
  duration: { ...theme.duration },
322
+ radii: { ...theme.radii },
323
+ fluidRanges: Object.fromEntries(
324
+ Object.entries(theme.fluidRanges).map(([name, range]) => [
325
+ name,
326
+ { min: range.min, max: range.max }
327
+ ])
328
+ ),
319
329
  fonts: theme.fonts.map((slot) => ({ slot: slot.slot, family: slot.family })),
320
330
  animations: Object.keys(theme.animations)
321
331
  };
@@ -382,7 +392,7 @@ function createEditorSession(options = {}) {
382
392
  }
383
393
 
384
394
  // src/entries/editor.ts
385
- var version = true ? "0.5.1" : "0.0.0-dev";
395
+ var version = true ? "0.6.0" : "0.0.0-dev";
386
396
  var EDITOR_API_VERSION = 1;
387
397
  var editorCapabilities = Object.freeze([
388
398
  "class-candidates",
@@ -400,7 +410,16 @@ var editorCapabilities = Object.freeze([
400
410
  "merge-analysis",
401
411
  "structured-diagnostics",
402
412
  "color-swatches",
403
- "editor-session"
413
+ "editor-session",
414
+ // `isSuppressible` — which diagnostic codes a `ri-disable` comment may name,
415
+ // so an editor can offer the comment only where it would work.
416
+ "diagnostic-suppression",
417
+ // `ThemeTokens.radii` and `ThemeTokens.fluidRanges`, for the named radii and
418
+ // named `@fluid` ranges that carry no token before this release.
419
+ "named-radii-and-fluid-ranges",
420
+ // `weightIsLoaded` / `describeLoadedWeights` — the RI-1504 coverage check,
421
+ // so an editor can answer "does any loaded font have this weight?".
422
+ "font-weight-coverage"
404
423
  ]);
405
424
  export {
406
425
  CANONICAL_COLOR_STOPS,
@@ -417,6 +436,7 @@ export {
417
436
  createThemeSnapshot,
418
437
  cssColorToHex,
419
438
  defaultTheme,
439
+ describeLoadedWeights,
420
440
  diagnosticFromWarning,
421
441
  editorCapabilities,
422
442
  enumerateClassNames,
@@ -427,6 +447,7 @@ export {
427
447
  findClosest,
428
448
  hasRIActivation,
429
449
  isSourceFile,
450
+ isSuppressible,
430
451
  listThemeTokens,
431
452
  listVariants,
432
453
  oklchToHex,
@@ -434,5 +455,6 @@ export {
434
455
  resolveColorSwatch,
435
456
  severityForCode,
436
457
  version,
437
- warningCode
458
+ warningCode,
459
+ weightIsLoaded
438
460
  };
@@ -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, j as CornerShape, A as AnimationDefinition, F as FluidConfig, b as CompilationSnapshot } from './index-DSgpB6bS.js';
2
2
 
3
3
  /** Provider discriminant for a slot, derived from its faces. */
4
4
  type FontProviderKind = "google" | "system" | "local" | "manual";
@@ -57,6 +57,21 @@ interface FontMetricsConfig {
57
57
  descent?: number;
58
58
  lineGap?: number;
59
59
  }
60
+ /**
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.
66
+ *
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.
70
+ */
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;
60
75
 
61
76
  /**
62
77
  * Font loading system — @font directive processing, @font-face generation,
@@ -165,6 +180,10 @@ interface ResolvedTheme {
165
180
  * `roundedShape` is null.
166
181
  */
167
182
  readonly roundedShapeScale: number;
183
+ /** Named radii from `@rounded { roof: 24px; }` — each one makes the class
184
+ * `rounded-<name>` and the token `--rounded-<name>`. A name that matches a
185
+ * built-in radius keyword replaces it; RI-1124 warns at definition. */
186
+ readonly radii: Readonly<Record<string, string>>;
168
187
  readonly shadows: Readonly<Record<string, string>>;
169
188
  readonly weights: Readonly<Record<string, number>>;
170
189
  readonly easing: Readonly<Record<string, string>>;
@@ -174,6 +193,10 @@ interface ResolvedTheme {
174
193
  readonly fluid: Readonly<FluidConfig>;
175
194
  readonly textFluid?: Readonly<FluidConfig>;
176
195
  readonly spacingFluid?: Readonly<FluidConfig>;
196
+ /** Named viewport ranges from `@fluid <name> { min; max; }` — each one makes
197
+ * the scope class `fluid-<name>` and the tokens `--fluid-<name>-{min,max}`.
198
+ * Ranges carry no unit: the ramp unit is baked per family. */
199
+ readonly fluidRanges: Readonly<Record<string, Readonly<FluidConfig>>>;
177
200
  readonly fonts: readonly FontSlot[];
178
201
  readonly preflight: Readonly<PreflightConfig>;
179
202
  readonly customUtilities: readonly CustomUtility[];
@@ -261,4 +284,4 @@ declare function createCompiler(): {
261
284
  fontOutputCache: Map<string, FontOutput>;
262
285
  };
263
286
 
264
- export { type CompilationResult as C, type ParsedDirective as P, type ResolvedTheme as R, type CompiledRule as a, createThemeSnapshot as b, createCompiler as c };
287
+ export { type CompilationResult as C, type ParsedDirective as P, type ResolvedTheme as R, type CompiledRule as a, createThemeSnapshot as b, createCompiler as c, describeLoadedWeights as d, weightIsLoaded as w };