UNPKG

eslint-plugin-better-tailwindcss

Version:

auto-wraps tailwind classes after a certain print width or class count into multiple lines to improve readability.

84 lines 3.32 kB
import { readFile } from "node:fs/promises"; import { dirname } from "node:path"; import { fork } from "@eslint/css-tree"; import { tailwind4 } from "tailwind-csstree"; import { withCache } from "../async-utils/cache.js"; import { resolveCss } from "../async-utils/resolvers.js"; const { findAll, generate, parse } = fork(tailwind4); export async function getCustomComponentClasses(ctx) { const resolvedPath = resolveCss(ctx, ctx.tailwindConfigPath); const files = await parseCssFilesDeep(ctx, resolvedPath); const utilities = Object.values(files).reduce((customComponentClasses, { ast }) => { customComponentClasses.push(...getCustomComponentUtilities(ast)); return customComponentClasses; }, []); return utilities; } async function parseCssFilesDeep(ctx, resolvedPath) { const cssFiles = {}; const cssFile = await parseCssFile(ctx, resolvedPath); if (!cssFile) { return cssFiles; } cssFiles[resolvedPath] = cssFile; for (const importPath of cssFile.imports) { const importedFiles = await parseCssFilesDeep(ctx, importPath); for (const importedFile in importedFiles) { cssFiles[importedFile] = importedFiles[importedFile]; } } return cssFiles; } const parseCssFile = async (ctx, resolvedPath) => withCache("css-file", resolvedPath, async () => { try { const content = await readFile(resolvedPath, "utf-8"); const ast = parse(content); const importNodes = findAll(ast, node => node.type === "Atrule" && node.name === "import" && node.prelude?.type === "AtrulePrelude"); const imports = importNodes.reduce((imports, importNode) => { if (importNode.type !== "Atrule" || !importNode.prelude) { return imports; } const importStatement = generate(importNode.prelude).match(/["'](?<importPath>[^"']+)["']/); if (!importStatement) { return imports; } const { importPath } = importStatement.groups || {}; const cwd = dirname(resolvedPath); const resolvedImportPath = resolveCss(ctx, importPath, cwd); if (resolvedImportPath) { imports.push(resolvedImportPath); } return imports; }, []); return { ast, imports }; } catch { } }); function getCustomComponentUtilities(ast) { const customComponentUtilities = []; const componentLayers = findAll(ast, node => { return node.type === "Atrule" && node.name === "layer" && node.prelude?.type === "AtrulePrelude" && generate(node.prelude).trim() === "components"; }); for (const layer of componentLayers) { const classSelectors = findAll(layer, node => node.type === "ClassSelector"); for (const classNode of classSelectors) { if (classNode.type !== "ClassSelector") { continue; } if (customComponentUtilities.includes(classNode.name)) { continue; } customComponentUtilities.push(classNode.name); } } return customComponentUtilities; } //# sourceMappingURL=custom-component-classes.async.v4.js.map