eslint-plugin-better-tailwindcss
Version:
auto-wraps tailwind classes after a certain print width or class count into multiple lines to improve readability.
75 lines • 3.43 kB
JavaScript
import { array, description, optional, pipe, strictObject, string } from "valibot";
import { createGetCustomComponentClasses, getCustomComponentClasses } from "../tailwindcss/custom-component-classes.js";
import { createGetPrefix, getPrefix } from "../tailwindcss/prefix.js";
import { createGetUnknownClasses, getUnknownClasses } from "../tailwindcss/unknown-classes.js";
import { async } from "../utils/context.js";
import { escapeForRegex } from "../async-utils/escape.js";
import { lintClasses } from "../utils/lint.js";
import { getCachedRegex } from "../async-utils/regex.js";
import { createRule } from "../utils/rule.js";
import { splitClasses } from "../utils/utils.js";
export const noUnknownClasses = createRule({
autofix: true,
category: "correctness",
description: "Disallow any css classes that are not registered in tailwindcss.",
docs: "https://github.com/schoero/eslint-plugin-better-tailwindcss/blob/main/docs/rules/no-unknown-classes.md",
name: "no-unknown-classes",
recommended: true,
messages: {
unknown: "Unknown class detected: {{ className }}"
},
schema: strictObject({
ignore: optional(pipe(array(string()), description("A list of classes that should be ignored by the rule.")), [])
}),
initialize: ctx => {
const { detectComponentClasses } = ctx.options;
createGetPrefix(ctx);
createGetUnknownClasses(ctx);
if (detectComponentClasses) {
createGetCustomComponentClasses(ctx);
}
},
lintLiterals: (ctx, literals) => lintLiterals(ctx, literals)
});
function lintLiterals(ctx, literals) {
const { ignore } = ctx.options;
const { prefix, suffix } = getPrefix(async(ctx));
const ignoredGroups = getCachedRegex(`^${escapeForRegex(`${prefix}${suffix}`)}group(?:\\/(\\S*))?$`);
const ignoredPeers = getCachedRegex(`^${escapeForRegex(`${prefix}${suffix}`)}peer(?:\\/(\\S*))?$`);
const customComponentClassRegexes = getCustomComponentClassRegexes(ctx);
for (const literal of literals) {
const classes = splitClasses(literal.content);
const { unknownClasses, warnings } = getUnknownClasses(async(ctx), classes);
if (unknownClasses.length === 0) {
continue;
}
lintClasses(ctx, literal, className => {
if (!unknownClasses.includes(className)) {
return;
}
if (ignore.some(ignoredClass => getCachedRegex(ignoredClass).test(className)) ||
customComponentClassRegexes?.some(customComponentClassesRegex => customComponentClassesRegex.test(className)) ||
ignoredGroups.test(className) ||
ignoredPeers.test(className)) {
return;
}
return {
data: {
className
},
id: "unknown",
warnings
};
});
}
}
function getCustomComponentClassRegexes(ctx) {
const { detectComponentClasses } = ctx.options;
if (!detectComponentClasses) {
return;
}
const { customComponentClasses } = getCustomComponentClasses(async(ctx));
const { prefix, suffix } = getPrefix(async(ctx));
return customComponentClasses.map(className => getCachedRegex(`^${escapeForRegex(`${prefix}${suffix}`)}(?:.*:)?${escapeForRegex(className)}$`));
}
//# sourceMappingURL=no-unknown-classes.js.map