rainbowindex 0.5.0 → 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.
- package/CHANGELOG.md +530 -0
- package/README.md +70 -39
- package/dist/browser.d.ts +2 -2
- package/dist/browser.mjs +1 -3
- package/dist/{chunk-CMB6BHVE.mjs → chunk-3LWJTLOJ.mjs} +62 -38
- package/dist/{chunk-KRZL4IDK.mjs → chunk-6U4IOFOS.mjs} +687 -859
- package/dist/{chunk-ZI5ZYNSU.mjs → chunk-KSNYSR3C.mjs} +5629 -5092
- package/dist/{chunk-DT5HYIM3.mjs → chunk-WK6S4HTC.mjs} +978 -901
- package/dist/{chunk-NXJZX6KI.mjs → chunk-ZR7XJMUN.mjs} +15 -8
- package/dist/cli.mjs +34 -11
- package/dist/editor.d.ts +35 -9
- package/dist/editor.mjs +34 -8
- package/dist/{index-Dp6i5TSv.d.ts → index-4Kyaq3IZ.d.ts} +29 -6
- package/dist/{context-ruu2x_jR.d.ts → index-DSgpB6bS.d.ts} +90 -69
- package/dist/index.d.ts +7 -4
- package/dist/index.mjs +14 -9
- package/dist/oxlint.d.ts +55 -0
- package/dist/oxlint.mjs +38 -0
- package/dist/{safelist-D9-Plqta.d.ts → safelist-CGCtF-Fr.d.ts} +2 -15
- package/dist/vite.mjs +67 -14
- package/package.json +7 -1
package/dist/index.mjs
CHANGED
|
@@ -3,19 +3,18 @@ import {
|
|
|
3
3
|
} from "./chunk-PD4ZXGJ6.mjs";
|
|
4
4
|
import {
|
|
5
5
|
postcss_default
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-3LWJTLOJ.mjs";
|
|
7
7
|
import {
|
|
8
8
|
finalizeProjectCompilation,
|
|
9
9
|
resolveGoogleFonts
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-WK6S4HTC.mjs";
|
|
11
11
|
import {
|
|
12
|
-
|
|
12
|
+
analyzeProjectCSSMemo,
|
|
13
13
|
createCompiler,
|
|
14
14
|
extractClassesFromSource,
|
|
15
15
|
pushWarningsDeduped
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-KSNYSR3C.mjs";
|
|
17
17
|
import {
|
|
18
|
-
DEFAULT_TEXT_SIZES,
|
|
19
18
|
createCompilationContext,
|
|
20
19
|
createRi,
|
|
21
20
|
defaultTheme,
|
|
@@ -25,17 +24,18 @@ import {
|
|
|
25
24
|
registerCustomTextSizes,
|
|
26
25
|
registerCustomUtility,
|
|
27
26
|
ri
|
|
28
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-6U4IOFOS.mjs";
|
|
29
28
|
|
|
30
29
|
// src/project/index.ts
|
|
31
30
|
async function compileProject(options) {
|
|
32
|
-
const analysis =
|
|
31
|
+
const analysis = analyzeProjectCSSMemo(options.css);
|
|
33
32
|
const classNames = /* @__PURE__ */ new Set();
|
|
34
33
|
if (options.classNames) {
|
|
35
34
|
for (const cls of options.classNames) {
|
|
36
35
|
classNames.add(cls);
|
|
37
36
|
}
|
|
38
37
|
}
|
|
38
|
+
const authored = new Set(classNames);
|
|
39
39
|
if (options.sources) {
|
|
40
40
|
const extractionWarnings = [];
|
|
41
41
|
for (const source of options.sources) {
|
|
@@ -43,11 +43,17 @@ async function compileProject(options) {
|
|
|
43
43
|
classNames.add(cls);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
pushWarningsDeduped(
|
|
46
|
+
pushWarningsDeduped(
|
|
47
|
+
analysis.warnings,
|
|
48
|
+
extractionWarnings,
|
|
49
|
+
analysis.warningSeen,
|
|
50
|
+
analysis.suppressed
|
|
51
|
+
);
|
|
47
52
|
}
|
|
48
53
|
return finalizeProjectCompilation({
|
|
49
54
|
css: options.css,
|
|
50
55
|
classNames,
|
|
56
|
+
authoredClassNames: authored,
|
|
51
57
|
analysis,
|
|
52
58
|
// Default to resolving google font weights so headless callers aren't silently
|
|
53
59
|
// stuck with "100 900" defaults; opt out with RI_OFFLINE / RI_FETCH_FONTS.
|
|
@@ -56,7 +62,6 @@ async function compileProject(options) {
|
|
|
56
62
|
});
|
|
57
63
|
}
|
|
58
64
|
export {
|
|
59
|
-
DEFAULT_TEXT_SIZES,
|
|
60
65
|
compileProject,
|
|
61
66
|
createCompilationContext,
|
|
62
67
|
createCompiler,
|
package/dist/oxlint.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Oxlint plugin for Rainbow Index projects.
|
|
3
|
+
*
|
|
4
|
+
* Oxlint loads a JS plugin by module specifier and reads its default export,
|
|
5
|
+
* so this entry keeps a default export even though the rest of the package
|
|
6
|
+
* prefers named ones. Register it from a Vite+ `vite.config.ts`:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* export default defineConfig({
|
|
10
|
+
* lint: {
|
|
11
|
+
* jsPlugins: [{ name: "rainbowindex", specifier: "rainbowindex/oxlint" }],
|
|
12
|
+
* rules: { "rainbowindex/prefer-ri": "error" },
|
|
13
|
+
* },
|
|
14
|
+
* });
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* The types below describe only the slice of the Oxlint rule API this plugin
|
|
18
|
+
* touches. They are declared here rather than imported from `@oxlint/plugins`
|
|
19
|
+
* because that package is a transitive dependency of Oxlint that a consumer
|
|
20
|
+
* cannot resolve, and its `definePlugin` / `defineRule` helpers are identity
|
|
21
|
+
* functions with no runtime behavior to reuse.
|
|
22
|
+
*/
|
|
23
|
+
interface ImportDeclarationNode {
|
|
24
|
+
source: {
|
|
25
|
+
value: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
interface RuleContext {
|
|
29
|
+
report(diagnostic: {
|
|
30
|
+
message: string;
|
|
31
|
+
node: ImportDeclarationNode;
|
|
32
|
+
}): void;
|
|
33
|
+
}
|
|
34
|
+
interface RuleVisitor {
|
|
35
|
+
ImportDeclaration(node: ImportDeclarationNode): void;
|
|
36
|
+
}
|
|
37
|
+
interface OxlintRule {
|
|
38
|
+
meta: {
|
|
39
|
+
type: "suggestion";
|
|
40
|
+
docs: {
|
|
41
|
+
description: string;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
create(context: RuleContext): RuleVisitor;
|
|
45
|
+
}
|
|
46
|
+
interface OxlintPlugin {
|
|
47
|
+
meta: {
|
|
48
|
+
name: string;
|
|
49
|
+
};
|
|
50
|
+
rules: Record<string, OxlintRule>;
|
|
51
|
+
}
|
|
52
|
+
declare const preferRiRule: OxlintRule;
|
|
53
|
+
declare const plugin: OxlintPlugin;
|
|
54
|
+
|
|
55
|
+
export { type OxlintPlugin, type OxlintRule, plugin as default, plugin, preferRiRule };
|
package/dist/oxlint.mjs
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// src/integrations/oxlint.ts
|
|
2
|
+
var REPLACED_PACKAGES = {
|
|
3
|
+
clsx: "composes conditional classes",
|
|
4
|
+
classnames: "composes conditional classes",
|
|
5
|
+
"tailwind-merge": "resolves class conflicts"
|
|
6
|
+
};
|
|
7
|
+
function packageName(specifier) {
|
|
8
|
+
return specifier.startsWith("@") ? specifier.split("/").slice(0, 2).join("/") : specifier.split("/")[0] ?? "";
|
|
9
|
+
}
|
|
10
|
+
var preferRiRule = {
|
|
11
|
+
meta: {
|
|
12
|
+
type: "suggestion",
|
|
13
|
+
docs: { description: "Merge class names with ri() from rainbowindex." }
|
|
14
|
+
},
|
|
15
|
+
create(context) {
|
|
16
|
+
return {
|
|
17
|
+
ImportDeclaration(node) {
|
|
18
|
+
const name = packageName(node.source.value);
|
|
19
|
+
const job = REPLACED_PACKAGES[name];
|
|
20
|
+
if (!job) return;
|
|
21
|
+
context.report({
|
|
22
|
+
message: `Import { ri } from "rainbowindex" instead of "${name}". ri() ${job}, and it reads the same theme the compiler emits.`,
|
|
23
|
+
node
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var plugin = {
|
|
30
|
+
meta: { name: "rainbowindex" },
|
|
31
|
+
rules: { "prefer-ri": preferRiRule }
|
|
32
|
+
};
|
|
33
|
+
var oxlint_default = plugin;
|
|
34
|
+
export {
|
|
35
|
+
oxlint_default as default,
|
|
36
|
+
plugin,
|
|
37
|
+
preferRiRule
|
|
38
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as CompilationSnapshot } from './
|
|
1
|
+
import { b as CompilationSnapshot } from './index-DSgpB6bS.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* ri() — class merge function.
|
|
@@ -51,19 +51,6 @@ declare function ri(...inputs: ClassInput[]): string;
|
|
|
51
51
|
*/
|
|
52
52
|
declare function createRi(snapshot?: CompilationSnapshot): (...inputs: ClassInput[]) => string;
|
|
53
53
|
|
|
54
|
-
/**
|
|
55
|
-
* Claim resolution for ri() — utility name → CSS properties it sets.
|
|
56
|
-
*
|
|
57
|
-
* Split from merge/index.ts so each merge file is one concept: this file owns
|
|
58
|
-
* the dual-mode dispatch tables and resolvePropsWith(); index.ts owns the
|
|
59
|
-
* merge algorithm; context.ts owns the compilation-context lifecycle.
|
|
60
|
-
*
|
|
61
|
-
* Everything here is immutable module-init data plus pure closures over it —
|
|
62
|
-
* the mutable published compilation state lives in context.ts, and callers
|
|
63
|
-
* thread it in through resolvePropsWith()'s parameters.
|
|
64
|
-
*/
|
|
65
|
-
declare const DEFAULT_TEXT_SIZES: readonly ["xs", "sm", "base", "lg", "xl", "2xl", "3xl", "4xl", "5xl"];
|
|
66
|
-
|
|
67
54
|
/**
|
|
68
55
|
* `safelist()` — declare utility classes that must be emitted regardless of
|
|
69
56
|
* whether the consumer's source files reference them directly.
|
|
@@ -106,4 +93,4 @@ declare const DEFAULT_TEXT_SIZES: readonly ["xs", "sm", "base", "lg", "xl", "2xl
|
|
|
106
93
|
*/
|
|
107
94
|
declare function safelist(...parts: ReadonlyArray<string | false | null | undefined>): string;
|
|
108
95
|
|
|
109
|
-
export {
|
|
96
|
+
export { createRi as c, ri as r, safelist as s };
|
package/dist/vite.mjs
CHANGED
|
@@ -1,21 +1,31 @@
|
|
|
1
1
|
import {
|
|
2
2
|
postcss_default
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import
|
|
3
|
+
} from "./chunk-3LWJTLOJ.mjs";
|
|
4
|
+
import {
|
|
5
|
+
disableScanChangeTracking,
|
|
6
|
+
enableScanChangeTracking,
|
|
7
|
+
enableSourceFileListCache,
|
|
8
|
+
invalidateSourceFileListCache,
|
|
9
|
+
markSourceFileChanged
|
|
10
|
+
} from "./chunk-WK6S4HTC.mjs";
|
|
5
11
|
import {
|
|
6
12
|
isSourceFile
|
|
7
13
|
} from "./chunk-3HRMFZGE.mjs";
|
|
8
14
|
import {
|
|
9
15
|
DIRECTIVE_TYPE_NAMES,
|
|
16
|
+
codepointCompare,
|
|
10
17
|
expandApplyGroups,
|
|
18
|
+
extractClassesFromSource,
|
|
11
19
|
findClosingBrace,
|
|
12
20
|
hasRIActivation,
|
|
13
21
|
isAtRuleBoundary,
|
|
14
|
-
isAtRuleNameChar
|
|
15
|
-
|
|
22
|
+
isAtRuleNameChar,
|
|
23
|
+
parseFileDisables,
|
|
24
|
+
warningCode
|
|
25
|
+
} from "./chunk-KSNYSR3C.mjs";
|
|
16
26
|
import {
|
|
17
27
|
devWarn
|
|
18
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-6U4IOFOS.mjs";
|
|
19
29
|
|
|
20
30
|
// src/integrations/vite.ts
|
|
21
31
|
import { existsSync } from "fs";
|
|
@@ -162,6 +172,7 @@ function rainbowindexVite() {
|
|
|
162
172
|
let logger;
|
|
163
173
|
const riCSSFiles = /* @__PURE__ */ new Set();
|
|
164
174
|
const fileVersions = /* @__PURE__ */ new Map();
|
|
175
|
+
const candidateSignatures = /* @__PURE__ */ new Map();
|
|
165
176
|
let hotUpdateCount = 0;
|
|
166
177
|
const PRUNE_INTERVAL = 50;
|
|
167
178
|
return {
|
|
@@ -169,19 +180,30 @@ function rainbowindexVite() {
|
|
|
169
180
|
enforce: "pre",
|
|
170
181
|
async config(config) {
|
|
171
182
|
root = config.root ?? process.cwd();
|
|
183
|
+
const patch = {};
|
|
184
|
+
const ignorePatterns = await riStylesheetPatterns(root);
|
|
185
|
+
if (ignorePatterns.length > 0) {
|
|
186
|
+
patch.fmt = { ignorePatterns };
|
|
187
|
+
}
|
|
172
188
|
if (!hasLocalPostCSSConfig(root)) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
plugins: [postcss_default()]
|
|
177
|
-
}
|
|
189
|
+
patch.css = {
|
|
190
|
+
postcss: {
|
|
191
|
+
plugins: [postcss_default()]
|
|
178
192
|
}
|
|
179
193
|
};
|
|
180
194
|
}
|
|
181
|
-
return
|
|
195
|
+
return patch;
|
|
182
196
|
},
|
|
183
197
|
configureServer(server) {
|
|
184
198
|
root = server.config?.root ?? process.cwd();
|
|
199
|
+
enableSourceFileListCache();
|
|
200
|
+
server.watcher?.on("add", invalidateSourceFileListCache);
|
|
201
|
+
server.watcher?.on("unlink", invalidateSourceFileListCache);
|
|
202
|
+
server.watcher?.on("unlinkDir", invalidateSourceFileListCache);
|
|
203
|
+
server.httpServer?.once("close", invalidateSourceFileListCache);
|
|
204
|
+
enableScanChangeTracking();
|
|
205
|
+
server.watcher?.on("change", (file) => markSourceFileChanged(file));
|
|
206
|
+
server.httpServer?.once("close", disableScanChangeTracking);
|
|
185
207
|
logger = {
|
|
186
208
|
info: (msg) => server.config.logger?.info?.(msg, { timestamp: true }),
|
|
187
209
|
warn: (msg) => server.config.logger?.warn?.(msg, { timestamp: true })
|
|
@@ -224,8 +246,11 @@ function rainbowindexVite() {
|
|
|
224
246
|
riCSSFiles.add(file);
|
|
225
247
|
let safe = rewriteDirectiveBodies(code);
|
|
226
248
|
const expandWarnings = [];
|
|
227
|
-
safe = expandApplyGroups(safe, expandWarnings);
|
|
249
|
+
safe = expandApplyGroups(safe, expandWarnings, file);
|
|
250
|
+
const suppressed = parseFileDisables(code);
|
|
228
251
|
for (const w of expandWarnings) {
|
|
252
|
+
const warned = warningCode(w);
|
|
253
|
+
if (warned !== null && suppressed.has(warned)) continue;
|
|
229
254
|
(logger?.warn ?? console.warn)(`[rainbowindex] ${w}`);
|
|
230
255
|
}
|
|
231
256
|
return safe !== code ? safe : null;
|
|
@@ -234,7 +259,8 @@ function rainbowindexVite() {
|
|
|
234
259
|
}
|
|
235
260
|
return null;
|
|
236
261
|
},
|
|
237
|
-
async handleHotUpdate(
|
|
262
|
+
async handleHotUpdate(ctx) {
|
|
263
|
+
const { file, server, modules } = ctx;
|
|
238
264
|
if (++hotUpdateCount % PRUNE_INTERVAL === 0) {
|
|
239
265
|
await pruneDeletedFiles();
|
|
240
266
|
}
|
|
@@ -243,6 +269,19 @@ function rainbowindexVite() {
|
|
|
243
269
|
return;
|
|
244
270
|
}
|
|
245
271
|
if (!isSourceFile(file)) return;
|
|
272
|
+
markSourceFileChanged(file);
|
|
273
|
+
const previous = candidateSignatures.get(file);
|
|
274
|
+
let signature;
|
|
275
|
+
try {
|
|
276
|
+
const content = await ctx.read();
|
|
277
|
+
signature = [...extractClassesFromSource({ path: file, content })].sort(codepointCompare).join(" ");
|
|
278
|
+
} catch {
|
|
279
|
+
candidateSignatures.delete(file);
|
|
280
|
+
}
|
|
281
|
+
if (signature !== void 0) {
|
|
282
|
+
candidateSignatures.set(file, signature);
|
|
283
|
+
if (previous === signature) return;
|
|
284
|
+
}
|
|
246
285
|
const extraModules = [];
|
|
247
286
|
const hmrModules = new Set(modules);
|
|
248
287
|
for (const cssFile of riCSSFiles) {
|
|
@@ -261,13 +300,14 @@ function rainbowindexVite() {
|
|
|
261
300
|
}
|
|
262
301
|
};
|
|
263
302
|
async function pruneDeletedFiles() {
|
|
264
|
-
const tracked = /* @__PURE__ */ new Set([...riCSSFiles, ...fileVersions.keys()]);
|
|
303
|
+
const tracked = /* @__PURE__ */ new Set([...riCSSFiles, ...fileVersions.keys(), ...candidateSignatures.keys()]);
|
|
265
304
|
const checks = [...tracked].map(async (file) => {
|
|
266
305
|
try {
|
|
267
306
|
await access(file);
|
|
268
307
|
} catch {
|
|
269
308
|
riCSSFiles.delete(file);
|
|
270
309
|
fileVersions.delete(file);
|
|
310
|
+
candidateSignatures.delete(file);
|
|
271
311
|
}
|
|
272
312
|
});
|
|
273
313
|
await Promise.all(checks);
|
|
@@ -292,6 +332,19 @@ function rainbowindexVite() {
|
|
|
292
332
|
}
|
|
293
333
|
}
|
|
294
334
|
}
|
|
335
|
+
async function riStylesheetPatterns(root2) {
|
|
336
|
+
const files = await findCSSFilesOnDisk(root2);
|
|
337
|
+
const active = await Promise.all(
|
|
338
|
+
files.map(async (file) => {
|
|
339
|
+
try {
|
|
340
|
+
return hasRIActivation(await readFile(file, "utf-8")) ? file : null;
|
|
341
|
+
} catch {
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
})
|
|
345
|
+
);
|
|
346
|
+
return active.filter((file) => file !== null).map((file) => relative(root2, file).replaceAll("\\", "/"));
|
|
347
|
+
}
|
|
295
348
|
async function findCSSFilesOnDisk(root2) {
|
|
296
349
|
const results = [];
|
|
297
350
|
await collectCSSFiles(root2, results);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rainbowindex",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "CSS-first system for building and maintaining consistent user interfaces",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"css",
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
"postcss",
|
|
17
17
|
"postcss-plugin",
|
|
18
18
|
"vite-plugin",
|
|
19
|
+
"vite-plus",
|
|
20
|
+
"oxlint",
|
|
19
21
|
"class-merge",
|
|
20
22
|
"classnames",
|
|
21
23
|
"tailwind",
|
|
@@ -65,6 +67,10 @@
|
|
|
65
67
|
"types": "./dist/vite.d.ts",
|
|
66
68
|
"default": "./dist/vite.mjs"
|
|
67
69
|
},
|
|
70
|
+
"./oxlint": {
|
|
71
|
+
"types": "./dist/oxlint.d.ts",
|
|
72
|
+
"default": "./dist/oxlint.mjs"
|
|
73
|
+
},
|
|
68
74
|
"./package.json": "./package.json"
|
|
69
75
|
},
|
|
70
76
|
"bin": {
|