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,16 +1,17 @@
1
1
  import {
2
2
  compileScannedProject
3
- } from "./chunk-F4VCBISU.mjs";
3
+ } from "./chunk-2T7V5XLK.mjs";
4
4
  import {
5
5
  APPLY_ALIASES,
6
6
  DIRECTIVE_NAMES_SET,
7
7
  MAX_DIRECTIVE_INPUT_SIZE,
8
8
  RI_IMPORT_SPECIFIER_ALTERNATION,
9
9
  applyVariantWrappers,
10
+ checkAppliedFontWeights,
10
11
  compileCSSFunctions,
11
12
  computeSortKey,
12
- expandVariantGroups,
13
- forEachApplyClass,
13
+ expandApplyBodyGroups,
14
+ forEachApplyClassList,
14
15
  hasApplyLikeDirective,
15
16
  hasCSSFunctions,
16
17
  hasRIActivation,
@@ -20,7 +21,7 @@ import {
20
21
  resolveUtilityDeclarations,
21
22
  resolveVariant,
22
23
  splitSelectorList
23
- } from "./chunk-PDORZSQX.mjs";
24
+ } from "./chunk-FJOZJIKB.mjs";
24
25
 
25
26
  // src/integrations/postcss/index.ts
26
27
  import postcss2 from "postcss";
@@ -95,7 +96,7 @@ function resolveFullNestingSelector(rule) {
95
96
  }
96
97
  return composeNestedSelectors(parts);
97
98
  }
98
- function processApply(root, theme, warnings) {
99
+ function processApply(root, theme, warnings, cssPath) {
99
100
  for (const alias of APPLY_ALIASES) {
100
101
  root.walkAtRules(alias, (atRule) => {
101
102
  atRule.name = "apply";
@@ -117,7 +118,7 @@ function processApply(root, theme, warnings) {
117
118
  const groupRoots = /* @__PURE__ */ new Set();
118
119
  root.walkAtRules("apply", (atRule) => {
119
120
  applyNodes.push(atRule);
120
- const params = expandVariantGroups(atRule.params, warnings);
121
+ const params = expandApplyBodyGroups(atRule.params, warnings, cssPath);
121
122
  const classNames = params.trim().split(/\s+/).filter(Boolean);
122
123
  classListByNode.set(atRule, classNames);
123
124
  if (classNames.includes("group")) {
@@ -174,6 +175,7 @@ function expandApply(atRule, classNames, theme, warnings, customVariantMap, grou
174
175
  atRule.remove();
175
176
  return;
176
177
  }
178
+ checkAppliedFontWeights(classNames, theme, warnings);
177
179
  const resolved = [];
178
180
  for (const className of classNames) {
179
181
  let entry = resolveCache.get(className);
@@ -313,9 +315,7 @@ function expandApply(atRule, classNames, theme, warnings, customVariantMap, grou
313
315
  bucket.nestedSelector,
314
316
  bucket.nestedBlocks
315
317
  );
316
- if (node) {
317
- docRoot().append(node);
318
- }
318
+ for (const branch of node) docRoot().append(branch);
319
319
  } else if (hasGroupVariants) {
320
320
  const node = buildVariantNode(
321
321
  fullNestingSelector(),
@@ -325,9 +325,7 @@ function expandApply(atRule, classNames, theme, warnings, customVariantMap, grou
325
325
  bucket.nestedSelector,
326
326
  bucket.nestedBlocks
327
327
  );
328
- if (node) {
329
- docRoot().append(node);
330
- }
328
+ for (const branch of node) docRoot().append(branch);
331
329
  } else {
332
330
  const node = buildVariantNode(
333
331
  baseSelector,
@@ -337,9 +335,9 @@ function expandApply(atRule, classNames, theme, warnings, customVariantMap, grou
337
335
  bucket.nestedSelector,
338
336
  bucket.nestedBlocks
339
337
  );
340
- if (node) {
341
- parentContainer.insertAfter(insertAfter, node);
342
- insertAfter = node;
338
+ for (const branch of node) {
339
+ parentContainer.insertAfter(insertAfter, branch);
340
+ insertAfter = branch;
343
341
  }
344
342
  }
345
343
  }
@@ -374,7 +372,10 @@ function findCustomUtility(utility, value, negative, theme) {
374
372
  function checkCustomApplyWarnings(cu, theme, warnings, visiting = /* @__PURE__ */ new Set()) {
375
373
  if (!hasApplyLikeDirective(cu.body)) return;
376
374
  const innerClasses = [];
377
- forEachApplyClass(cu.body, (cls) => innerClasses.push(cls));
375
+ forEachApplyClassList(cu.body, (classes) => {
376
+ checkAppliedFontWeights(classes, theme, warnings);
377
+ innerClasses.push(...classes);
378
+ });
378
379
  if (innerClasses.length === 0) return;
379
380
  if (visiting.has(cu.name)) {
380
381
  warnings.push(
@@ -470,8 +471,20 @@ function buildNestedBlockNode(block, sourceNode, important) {
470
471
  return node;
471
472
  }
472
473
  function buildVariantNode(baseSelector, wrappers, decls, sourceNode, nestedSelector, nestedBlocks) {
473
- if (decls.length === 0 && nestedBlocks.length === 0) return null;
474
- const { selector, atRules, startingStyle } = applyVariantWrappers(baseSelector, wrappers);
474
+ if (decls.length === 0 && nestedBlocks.length === 0) return [];
475
+ return applyVariantWrappers(baseSelector, wrappers).map(
476
+ ({ selector, atRules, startingStyle }) => buildBranchNode(
477
+ selector,
478
+ atRules,
479
+ startingStyle,
480
+ decls,
481
+ sourceNode,
482
+ nestedSelector,
483
+ nestedBlocks
484
+ )
485
+ );
486
+ }
487
+ function buildBranchNode(selector, atRules, startingStyle, decls, sourceNode, nestedSelector, nestedBlocks) {
475
488
  const rule = applySource(postcss.rule({ selector }), sourceNode);
476
489
  let declTarget = rule;
477
490
  if (nestedSelector) {
@@ -582,28 +595,29 @@ var rainbowindex = (options = {}) => {
582
595
  if (!hasActivation) {
583
596
  return;
584
597
  }
598
+ const from = root.source?.input?.file ?? root.source?.input?.id ?? root.source?.input?.from ?? "<rainbowindex>";
585
599
  const { compiled, warningSeen } = await compileScannedProject({
586
600
  css: rawCSS,
587
601
  cwd,
602
+ cssPath: from,
588
603
  surfacePatterns: options.sources,
589
604
  onInvalidPattern: (err) => `[RI-1015] ${err}`
590
605
  });
591
606
  const compilationWarnings = compiled.warnings;
592
- const from = root.source?.input?.file ?? root.source?.input?.id ?? root.source?.input?.from ?? "<rainbowindex>";
593
607
  stripRIDirectiveNodes(root);
594
608
  const slotWarnings = [];
595
609
  warnStandaloneSlots(root, slotWarnings);
596
- pushWarningsDeduped(compilationWarnings, slotWarnings, warningSeen);
610
+ pushWarningsDeduped(compilationWarnings, slotWarnings, warningSeen, compiled.suppressed);
597
611
  const applyWarnings = [];
598
- processApply(root, compiled.theme, applyWarnings);
599
- pushWarningsDeduped(compilationWarnings, applyWarnings, warningSeen);
612
+ processApply(root, compiled.theme, applyWarnings, from);
613
+ pushWarningsDeduped(compilationWarnings, applyWarnings, warningSeen, compiled.suppressed);
600
614
  if (compiled.sections.length > 0) {
601
615
  const generatedRoot = postcss2.parse(compiled.sections.join("\n\n"), { from });
602
616
  root.prepend(generatedRoot.nodes);
603
617
  }
604
618
  const cssFnWarnings = [];
605
619
  processCSSFunctions(root, compiled.theme, cssFnWarnings);
606
- pushWarningsDeduped(compilationWarnings, cssFnWarnings, warningSeen);
620
+ pushWarningsDeduped(compilationWarnings, cssFnWarnings, warningSeen, compiled.suppressed);
607
621
  for (const warning of compilationWarnings) {
608
622
  result.warn(warning);
609
623
  }
@@ -0,0 +1,217 @@
1
+ import {
2
+ createEditorSession
3
+ } from "./chunk-PZDVDEZJ.mjs";
4
+ import {
5
+ CSS_ENTRY_CANDIDATES,
6
+ outermostCandidates
7
+ } from "./chunk-WBESS2ZD.mjs";
8
+ import {
9
+ createNodeImportResolver
10
+ } from "./chunk-W756NVYI.mjs";
11
+ import {
12
+ isSourceFile
13
+ } from "./chunk-X66Z2YHT.mjs";
14
+ import {
15
+ extractClassCandidates,
16
+ hasRIActivation
17
+ } from "./chunk-FJOZJIKB.mjs";
18
+
19
+ // src/integrations/lint/theme.ts
20
+ import { existsSync, readFileSync, statSync } from "fs";
21
+ import { isAbsolute, resolve as resolvePath } from "path";
22
+ function findCSSEntry(cwd) {
23
+ for (const candidate of CSS_ENTRY_CANDIDATES) {
24
+ const path = resolvePath(cwd, candidate);
25
+ if (!existsSync(path)) continue;
26
+ try {
27
+ if (hasRIActivation(readFileSync(path, "utf8"))) return path;
28
+ } catch {
29
+ }
30
+ }
31
+ return null;
32
+ }
33
+ var sessions = /* @__PURE__ */ new Map();
34
+ function mtimeOf(path) {
35
+ try {
36
+ return statSync(path).mtimeMs;
37
+ } catch {
38
+ return -1;
39
+ }
40
+ }
41
+ function stampsFor(session, entry) {
42
+ const stamps = /* @__PURE__ */ new Map([[entry, mtimeOf(entry)]]);
43
+ for (const file of session.importedFiles) stamps.set(file, mtimeOf(file));
44
+ return stamps;
45
+ }
46
+ function isStale(cached) {
47
+ for (const [path, stamp] of cached.stamps) {
48
+ if (mtimeOf(path) !== stamp) return true;
49
+ }
50
+ return false;
51
+ }
52
+ function getSession(options = {}) {
53
+ const cwd = options.cwd ?? process.cwd();
54
+ const entry = options.css ? isAbsolute(options.css) ? options.css : resolvePath(cwd, options.css) : findCSSEntry(cwd);
55
+ if (entry === null) return null;
56
+ const cached = sessions.get(entry);
57
+ if (cached && !isStale(cached)) return cached.session;
58
+ let css;
59
+ try {
60
+ css = readFileSync(entry, "utf8");
61
+ } catch {
62
+ sessions.delete(entry);
63
+ return null;
64
+ }
65
+ const session = createEditorSession({
66
+ css,
67
+ cssPath: entry,
68
+ resolveImport: createNodeImportResolver({ cwd })
69
+ });
70
+ sessions.set(entry, { session, stamps: stampsFor(session, entry) });
71
+ return session;
72
+ }
73
+ function clearSessionCache() {
74
+ sessions.clear();
75
+ }
76
+
77
+ // src/integrations/lint/rules.ts
78
+ function sourceCodeOf(context) {
79
+ return context.sourceCode ?? context.getSourceCode?.() ?? null;
80
+ }
81
+ function scanPathFor(context) {
82
+ const filename = context.filename ?? context.getFilename?.() ?? "<input>";
83
+ return isSourceFile(filename) ? filename : `${filename}.tsx`;
84
+ }
85
+ function optionsOf(context) {
86
+ const first = context.options?.[0];
87
+ const options = first && typeof first === "object" ? { ...first } : {};
88
+ options.cwd ??= context.cwd ?? process.cwd();
89
+ return options;
90
+ }
91
+ var AUTHORED_ORIGINS = /* @__PURE__ */ new Set(["attribute", "helper", "safelist"]);
92
+ function authoredCandidates(source, path) {
93
+ return outermostCandidates(extractClassCandidates({ content: source, path })).filter(
94
+ (candidate) => AUTHORED_ORIGINS.has(candidate.origin)
95
+ );
96
+ }
97
+ function locOf(sourceCode, candidate) {
98
+ return {
99
+ start: sourceCode.getLocFromIndex(candidate.start),
100
+ end: sourceCode.getLocFromIndex(candidate.end)
101
+ };
102
+ }
103
+ var THEME_OPTION_SCHEMA = [
104
+ {
105
+ type: "object",
106
+ properties: { css: { type: "string" }, cwd: { type: "string" } },
107
+ additionalProperties: false
108
+ }
109
+ ];
110
+ var noUnknownClassRule = {
111
+ meta: {
112
+ type: "problem",
113
+ docs: {
114
+ description: "Every class in a class position must compile against the project theme."
115
+ },
116
+ hasSuggestions: true,
117
+ schema: THEME_OPTION_SCHEMA
118
+ },
119
+ create(context) {
120
+ const sourceCode = sourceCodeOf(context);
121
+ if (sourceCode === null) return {};
122
+ const session = getSession(optionsOf(context));
123
+ if (session === null) return {};
124
+ return {
125
+ Program(node) {
126
+ const text = sourceCode.getText();
127
+ for (const candidate of authoredCandidates(text, scanPathFor(context))) {
128
+ const result = session.inspector.validate(candidate.value);
129
+ if (result.ok) continue;
130
+ const detail = result.reason === "unknown-variant" ? `Unknown variant "${result.offender}"` : result.reason === "invalid-arbitrary" ? `Invalid arbitrary value in "${result.offender}"` : `Unknown utility "${result.offender}"`;
131
+ const hint = result.suggestion ? ` Did you mean "${result.suggestion}"?` : "";
132
+ context.report({
133
+ message: `${detail} \u2014 "${candidate.value}" compiles to nothing.${hint}`,
134
+ node,
135
+ loc: locOf(sourceCode, candidate),
136
+ suggest: suggestionFor(text, candidate, result.offender, result.suggestion)
137
+ });
138
+ }
139
+ }
140
+ };
141
+ }
142
+ };
143
+ function suggestionFor(text, candidate, offender, suggestion) {
144
+ if (suggestion === void 0) return void 0;
145
+ const slice = text.slice(candidate.start, candidate.end);
146
+ const at = slice.indexOf(offender);
147
+ if (at === -1 || slice.indexOf(offender, at + 1) !== -1) return void 0;
148
+ const range = [candidate.start + at, candidate.start + at + offender.length];
149
+ return [
150
+ {
151
+ desc: `Replace "${offender}" with "${suggestion}"`,
152
+ fix: (fixer) => fixer.replaceTextRange(range, suggestion)
153
+ }
154
+ ];
155
+ }
156
+ function classRuns(text, candidates) {
157
+ const runs = [];
158
+ let current = [];
159
+ let previousEnd = -1;
160
+ for (const candidate of candidates) {
161
+ const gap = previousEnd === -1 ? null : text.slice(previousEnd, candidate.start);
162
+ if (gap !== null && gap.trim() === "") {
163
+ current.push(candidate);
164
+ } else {
165
+ if (current.length > 0) runs.push(current);
166
+ current = [candidate];
167
+ }
168
+ previousEnd = candidate.end;
169
+ }
170
+ if (current.length > 0) runs.push(current);
171
+ return runs;
172
+ }
173
+ var noConflictingClassesRule = {
174
+ meta: {
175
+ type: "problem",
176
+ docs: {
177
+ description: "One class string must not contain classes that override each other."
178
+ },
179
+ schema: THEME_OPTION_SCHEMA
180
+ },
181
+ create(context) {
182
+ const sourceCode = sourceCodeOf(context);
183
+ if (sourceCode === null) return {};
184
+ const session = getSession(optionsOf(context));
185
+ if (session === null) return {};
186
+ return {
187
+ Program(node) {
188
+ const text = sourceCode.getText();
189
+ for (const run of classRuns(text, authoredCandidates(text, scanPathFor(context)))) {
190
+ if (run.length < 2) continue;
191
+ const analysis = session.analyzeMerge(run.map((candidate) => candidate.value));
192
+ for (const drop of analysis.dropped) {
193
+ const winners = drop.overriddenBy.map((index) => `"${run[index]?.value ?? "?"}"`).join(", ");
194
+ context.report({
195
+ message: `"${drop.className}" is overridden by ${winners} in the same class string, so it has no effect.`,
196
+ node,
197
+ loc: locOf(sourceCode, run[drop.index])
198
+ });
199
+ }
200
+ }
201
+ }
202
+ };
203
+ }
204
+ };
205
+ var rules = Object.freeze({
206
+ "no-unknown-class": noUnknownClassRule,
207
+ "no-conflicting-classes": noConflictingClassesRule
208
+ });
209
+
210
+ export {
211
+ findCSSEntry,
212
+ getSession,
213
+ clearSessionCache,
214
+ noUnknownClassRule,
215
+ noConflictingClassesRule,
216
+ rules
217
+ };
@@ -0,0 +1,33 @@
1
+ import {
2
+ MAX_DIRECTIVE_INPUT_SIZE
3
+ } from "./chunk-FJOZJIKB.mjs";
4
+
5
+ // src/project/resolve-import.ts
6
+ import { readFileSync, statSync } from "fs";
7
+ import { createRequire } from "module";
8
+ import { dirname, resolve as resolvePath } from "path";
9
+ var MAX_IMPORT_FILE_SIZE = MAX_DIRECTIVE_INPUT_SIZE;
10
+ function readIfSmallEnough(path) {
11
+ const size = statSync(path).size;
12
+ if (size > MAX_IMPORT_FILE_SIZE) return null;
13
+ const content = readFileSync(path, "utf8");
14
+ return { path, content: content.charCodeAt(0) === 65279 ? content.slice(1) : content };
15
+ }
16
+ function createNodeImportResolver(options) {
17
+ return (specifier, from) => {
18
+ try {
19
+ if (specifier.startsWith("./") || specifier.startsWith("../")) {
20
+ const base = from === void 0 ? options.cwd : dirname(from);
21
+ return readIfSmallEnough(resolvePath(base, specifier));
22
+ }
23
+ const anchor = from ?? resolvePath(options.cwd, "__ri_import_anchor__.js");
24
+ return readIfSmallEnough(createRequire(anchor).resolve(specifier));
25
+ } catch {
26
+ return null;
27
+ }
28
+ };
29
+ }
30
+
31
+ export {
32
+ createNodeImportResolver
33
+ };