uilint-eslint 0.1.20 → 0.1.22
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/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1246,7 +1246,10 @@ function analyzeComponentLibraries(filePath, componentName, visited) {
|
|
|
1246
1246
|
library: usedLibrary
|
|
1247
1247
|
});
|
|
1248
1248
|
} else {
|
|
1249
|
-
const resolvedPath = resolveImportPath(
|
|
1249
|
+
const resolvedPath = resolveImportPath(
|
|
1250
|
+
usedComponent.importSource,
|
|
1251
|
+
filePath
|
|
1252
|
+
);
|
|
1250
1253
|
if (resolvedPath) {
|
|
1251
1254
|
const cacheKey = `${resolvedPath}::${usedComponent.name}`;
|
|
1252
1255
|
if (!visited.has(cacheKey)) {
|
|
@@ -1255,7 +1258,10 @@ function analyzeComponentLibraries(filePath, componentName, visited) {
|
|
|
1255
1258
|
if (componentLibraryCache.has(cacheKey)) {
|
|
1256
1259
|
nestedInfo = componentLibraryCache.get(cacheKey);
|
|
1257
1260
|
} else {
|
|
1258
|
-
const resolvedExport = resolveExport(
|
|
1261
|
+
const resolvedExport = resolveExport(
|
|
1262
|
+
usedComponent.name,
|
|
1263
|
+
resolvedPath
|
|
1264
|
+
);
|
|
1259
1265
|
const actualFilePath = resolvedExport?.filePath ?? resolvedPath;
|
|
1260
1266
|
const actualComponentName = resolvedExport?.localName ?? usedComponent.name;
|
|
1261
1267
|
nestedInfo = analyzeComponentLibraries(
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/create-rule.ts","../src/rules/no-arbitrary-tailwind.ts","../src/rules/consistent-spacing.ts","../src/rules/consistent-dark-mode.ts","../src/rules/no-direct-store-import.ts","../src/rules/prefer-zustand-state-management.ts","../src/utils/export-resolver.ts","../src/utils/component-parser.ts","../src/utils/import-graph.ts","../src/rules/no-mixed-component-libraries.ts","../src/rules/semantic.ts","../src/utils/cache.ts","../src/utils/styleguide-loader.ts","../src/rule-registry.ts","../src/index.ts"],"sourcesContent":["/**\n * Rule creation helper using @typescript-eslint/utils\n */\n\nimport { ESLintUtils } from \"@typescript-eslint/utils\";\n\nexport const createRule = ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/peter-suggate/uilint/blob/main/packages/uilint-eslint/docs/rules/${name}.md`\n);\n","/**\n * Rule: no-arbitrary-tailwind\n *\n * Forbids arbitrary Tailwind values like w-[123px], bg-[#fff], etc.\n */\n\nimport { createRule } from \"../utils/create-rule.js\";\nimport type { TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noArbitraryValue\";\ntype Options = [];\n\n// Regex to match arbitrary Tailwind values: word-[anything]\nconst ARBITRARY_VALUE_REGEX = /\\b[\\w-]+-\\[[^\\]]+\\]/g;\n\nexport default createRule<Options, MessageIds>({\n name: \"no-arbitrary-tailwind\",\n meta: {\n type: \"problem\",\n docs: {\n description: \"Forbid arbitrary Tailwind values like w-[123px]\",\n },\n messages: {\n noArbitraryValue:\n \"Avoid arbitrary Tailwind value '{{value}}'. Use the spacing/color scale instead.\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n return {\n // Check className attributes in JSX\n JSXAttribute(node) {\n if (\n node.name.type === \"JSXIdentifier\" &&\n (node.name.name === \"className\" || node.name.name === \"class\")\n ) {\n const value = node.value;\n\n // Handle string literal: className=\"...\"\n if (value?.type === \"Literal\" && typeof value.value === \"string\") {\n checkClassString(context, value, value.value);\n }\n\n // Handle JSX expression: className={...}\n if (value?.type === \"JSXExpressionContainer\") {\n const expr = value.expression;\n\n // Direct string: className={\"...\"}\n if (expr.type === \"Literal\" && typeof expr.value === \"string\") {\n checkClassString(context, expr, expr.value);\n }\n\n // Template literal: className={`...`}\n if (expr.type === \"TemplateLiteral\") {\n for (const quasi of expr.quasis) {\n checkClassString(context, quasi, quasi.value.raw);\n }\n }\n }\n }\n },\n\n // Check cn(), clsx(), classnames() calls\n CallExpression(node) {\n if (node.callee.type !== \"Identifier\") return;\n const name = node.callee.name;\n\n if (name === \"cn\" || name === \"clsx\" || name === \"classnames\") {\n for (const arg of node.arguments) {\n if (arg.type === \"Literal\" && typeof arg.value === \"string\") {\n checkClassString(context, arg, arg.value);\n }\n if (arg.type === \"TemplateLiteral\") {\n for (const quasi of arg.quasis) {\n checkClassString(context, quasi, quasi.value.raw);\n }\n }\n }\n }\n },\n };\n },\n});\n\nfunction checkClassString(\n context: Parameters<\n ReturnType<typeof createRule<[], \"noArbitraryValue\">>[\"create\"]\n >[0],\n node: TSESTree.Node,\n classString: string\n) {\n const matches = classString.matchAll(ARBITRARY_VALUE_REGEX);\n\n for (const match of matches) {\n // Ignore data attributes (e.g., data-[value], data-test-[something])\n if (match[0].startsWith(\"data-\")) {\n continue;\n }\n\n context.report({\n node,\n messageId: \"noArbitraryValue\",\n data: { value: match[0] },\n });\n }\n}\n","/**\n * Rule: consistent-spacing\n *\n * Enforces use of spacing scale values in gap, padding, margin utilities.\n */\n\nimport { createRule } from \"../utils/create-rule.js\";\nimport type { TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"invalidSpacing\";\ntype Options = [\n {\n scale?: number[];\n }\n];\n\n// Default Tailwind spacing scale\nconst DEFAULT_SCALE = [\n 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 24,\n 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 96,\n];\n\n// Spacing utilities that take numeric values\nconst SPACING_PREFIXES = [\n \"p-\",\n \"px-\",\n \"py-\",\n \"pt-\",\n \"pr-\",\n \"pb-\",\n \"pl-\",\n \"ps-\",\n \"pe-\",\n \"m-\",\n \"mx-\",\n \"my-\",\n \"mt-\",\n \"mr-\",\n \"mb-\",\n \"ml-\",\n \"ms-\",\n \"me-\",\n \"gap-\",\n \"gap-x-\",\n \"gap-y-\",\n \"space-x-\",\n \"space-y-\",\n \"inset-\",\n \"inset-x-\",\n \"inset-y-\",\n \"top-\",\n \"right-\",\n \"bottom-\",\n \"left-\",\n \"w-\",\n \"h-\",\n \"min-w-\",\n \"min-h-\",\n \"max-w-\",\n \"max-h-\",\n \"size-\",\n];\n\n// Build regex to match spacing utilities with numeric values\nfunction buildSpacingRegex(): RegExp {\n const prefixes = SPACING_PREFIXES.map((p) => p.replace(\"-\", \"\\\\-\")).join(\"|\");\n // Match prefix followed by a number (possibly with decimal)\n return new RegExp(`\\\\b(${prefixes})(\\\\d+\\\\.?\\\\d*)\\\\b`, \"g\");\n}\n\nconst SPACING_REGEX = buildSpacingRegex();\n\nexport default createRule<Options, MessageIds>({\n name: \"consistent-spacing\",\n meta: {\n type: \"suggestion\",\n docs: {\n description: \"Enforce spacing scale (no magic numbers in gap/padding)\",\n },\n messages: {\n invalidSpacing:\n \"Spacing value '{{value}}' is not in the allowed scale. Use one of: {{allowed}}\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n scale: {\n type: \"array\",\n items: { type: \"number\" },\n },\n },\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [{ scale: DEFAULT_SCALE }],\n create(context) {\n const options = context.options[0] || {};\n const scale = new Set((options.scale || DEFAULT_SCALE).map(String));\n const scaleList = [...scale].slice(0, 10).join(\", \") + \"...\";\n\n return {\n // Check className attributes in JSX\n JSXAttribute(node) {\n if (\n node.name.type === \"JSXIdentifier\" &&\n (node.name.name === \"className\" || node.name.name === \"class\")\n ) {\n const value = node.value;\n\n if (value?.type === \"Literal\" && typeof value.value === \"string\") {\n checkSpacing(context, node, value.value, scale, scaleList);\n }\n\n if (value?.type === \"JSXExpressionContainer\") {\n const expr = value.expression;\n if (expr.type === \"Literal\" && typeof expr.value === \"string\") {\n checkSpacing(context, node, expr.value, scale, scaleList);\n }\n if (expr.type === \"TemplateLiteral\") {\n for (const quasi of expr.quasis) {\n checkSpacing(context, node, quasi.value.raw, scale, scaleList);\n }\n }\n }\n }\n },\n\n // Check cn(), clsx(), classnames() calls\n CallExpression(node) {\n if (node.callee.type !== \"Identifier\") return;\n const name = node.callee.name;\n\n if (name === \"cn\" || name === \"clsx\" || name === \"classnames\") {\n for (const arg of node.arguments) {\n if (arg.type === \"Literal\" && typeof arg.value === \"string\") {\n checkSpacing(context, arg, arg.value, scale, scaleList);\n }\n if (arg.type === \"TemplateLiteral\") {\n for (const quasi of arg.quasis) {\n checkSpacing(context, quasi, quasi.value.raw, scale, scaleList);\n }\n }\n }\n }\n },\n };\n },\n});\n\nfunction checkSpacing(\n context: Parameters<\n ReturnType<typeof createRule<Options, \"invalidSpacing\">>[\"create\"]\n >[0],\n node: TSESTree.Node,\n classString: string,\n scale: Set<string>,\n scaleList: string\n) {\n // Reset regex state\n SPACING_REGEX.lastIndex = 0;\n\n let match;\n while ((match = SPACING_REGEX.exec(classString)) !== null) {\n const [, , value] = match;\n if (value && !scale.has(value)) {\n context.report({\n node,\n messageId: \"invalidSpacing\",\n data: { value, allowed: scaleList },\n });\n }\n }\n}\n","/**\n * Rule: consistent-dark-mode\n *\n * Ensures consistent dark mode theming in Tailwind CSS classes.\n * - Error: When some color classes have dark: variants but others don't within the same element\n * - Warning: When Tailwind color classes are used in a file but no dark: theming exists\n */\n\nimport { createRule } from \"../utils/create-rule.js\";\nimport type { TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"inconsistentDarkMode\" | \"missingDarkMode\";\ntype Options = [\n {\n /** Whether to warn when no dark mode classes are found in a file that uses Tailwind colors. Default: true */\n warnOnMissingDarkMode?: boolean;\n }?\n];\n\n// Color-related class prefixes that should have dark mode variants\nconst COLOR_PREFIXES = [\n \"bg-\",\n \"text-\",\n \"border-\",\n \"border-t-\",\n \"border-r-\",\n \"border-b-\",\n \"border-l-\",\n \"border-x-\",\n \"border-y-\",\n \"ring-\",\n \"ring-offset-\",\n \"divide-\",\n \"outline-\",\n \"shadow-\",\n \"accent-\",\n \"caret-\",\n \"fill-\",\n \"stroke-\",\n \"decoration-\",\n \"placeholder-\",\n \"from-\",\n \"via-\",\n \"to-\",\n];\n\n// Values that don't need dark variants (colorless or inherited)\nconst EXEMPT_SUFFIXES = [\"transparent\", \"inherit\", \"current\", \"auto\", \"none\"];\n\n// Known non-color utilities that use color prefixes\n// These are utilities like text-lg (font size), text-center (alignment), etc.\nconst NON_COLOR_UTILITIES = new Set([\n // Exempt values (colorless or inherited) - don't need dark variants\n \"transparent\",\n \"inherit\",\n \"current\",\n \"auto\",\n \"none\",\n // text- utilities that aren't colors\n \"xs\",\n \"sm\",\n \"base\",\n \"lg\",\n \"xl\",\n \"2xl\",\n \"3xl\",\n \"4xl\",\n \"5xl\",\n \"6xl\",\n \"7xl\",\n \"8xl\",\n \"9xl\",\n \"left\",\n \"center\",\n \"right\",\n \"justify\",\n \"start\",\n \"end\",\n \"wrap\",\n \"nowrap\",\n \"balance\",\n \"pretty\",\n \"ellipsis\",\n \"clip\",\n // border- utilities that aren't colors\n \"0\",\n \"2\",\n \"4\",\n \"8\",\n \"solid\",\n \"dashed\",\n \"dotted\",\n \"double\",\n \"hidden\",\n \"collapse\",\n \"separate\",\n // shadow- utilities that aren't colors\n // Note: \"sm\", \"lg\", \"xl\", \"2xl\" already included above\n \"md\",\n \"inner\",\n // ring- utilities that aren't colors\n // Note: \"0\", \"2\", \"4\", \"8\" already included above\n \"1\",\n \"inset\",\n // outline- utilities that aren't colors\n // Note: numeric values already included\n \"offset-0\",\n \"offset-1\",\n \"offset-2\",\n \"offset-4\",\n \"offset-8\",\n // decoration- utilities that aren't colors\n // Note: \"solid\", \"double\", \"dotted\", \"dashed\" already included\n \"wavy\",\n \"from-font\",\n \"clone\",\n \"slice\",\n // divide- utilities that aren't colors\n \"x\",\n \"y\",\n \"x-0\",\n \"x-2\",\n \"x-4\",\n \"x-8\",\n \"y-0\",\n \"y-2\",\n \"y-4\",\n \"y-8\",\n \"x-reverse\",\n \"y-reverse\",\n // gradient direction utilities (from-, via-, to- prefixes)\n \"t\",\n \"tr\",\n \"r\",\n \"br\",\n \"b\",\n \"bl\",\n \"l\",\n \"tl\",\n]);\n\n// Semantic color names used by theming systems like shadcn\n// These are CSS variable-based colors that handle dark mode automatically\nconst SEMANTIC_COLOR_NAMES = new Set([\n // Core shadcn colors\n \"background\",\n \"foreground\",\n // Component colors\n \"card\",\n \"card-foreground\",\n \"popover\",\n \"popover-foreground\",\n \"primary\",\n \"primary-foreground\",\n \"secondary\",\n \"secondary-foreground\",\n \"muted\",\n \"muted-foreground\",\n \"accent\",\n \"accent-foreground\",\n \"destructive\",\n \"destructive-foreground\",\n // Form/UI colors\n \"border\",\n \"input\",\n \"ring\",\n // Sidebar colors (shadcn sidebar component)\n \"sidebar\",\n \"sidebar-foreground\",\n \"sidebar-border\",\n \"sidebar-primary\",\n \"sidebar-primary-foreground\",\n \"sidebar-accent\",\n \"sidebar-accent-foreground\",\n \"sidebar-ring\",\n]);\n\n// Pattern for semantic chart colors (chart-1, chart-2, etc.)\nconst CHART_COLOR_PATTERN = /^chart-\\d+$/;\n\n/**\n * Check if a class has 'dark' in its variant chain\n */\nfunction hasDarkVariant(className: string): boolean {\n const parts = className.split(\":\");\n // All parts except the last are variants\n const variants = parts.slice(0, -1);\n return variants.includes(\"dark\");\n}\n\n/**\n * Get the base class (without any variants like hover:, dark:, md:, etc.)\n */\nfunction getBaseClass(className: string): string {\n const parts = className.split(\":\");\n return parts[parts.length - 1] || \"\";\n}\n\n/**\n * Find the color prefix this class uses, if any\n */\nfunction getColorPrefix(baseClass: string): string | null {\n // Sort by length descending to match more specific prefixes first\n // (e.g., \"border-t-\" before \"border-\")\n const sortedPrefixes = [...COLOR_PREFIXES].sort(\n (a, b) => b.length - a.length\n );\n return sortedPrefixes.find((p) => baseClass.startsWith(p)) || null;\n}\n\n/**\n * Check if the value is a semantic/themed color (e.g., shadcn)\n * These colors use CSS variables that automatically handle dark mode\n */\nfunction isSemanticColor(value: string): boolean {\n // Check for exact semantic color names\n if (SEMANTIC_COLOR_NAMES.has(value)) {\n return true;\n }\n\n // Check for chart colors (chart-1, chart-2, etc.)\n if (CHART_COLOR_PATTERN.test(value)) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Check if the value after the prefix looks like a color value\n * Uses an exclusion-based approach: anything that's not a known non-color utility\n * and not a semantic color is treated as a potential color.\n */\nfunction isColorValue(baseClass: string, prefix: string): boolean {\n const value = baseClass.slice(prefix.length);\n\n // Empty value is not a color\n if (!value) {\n return false;\n }\n\n // Check if it's a semantic/themed color (exempt from dark mode requirements)\n if (isSemanticColor(value)) {\n return false;\n }\n\n // Check if it's a known non-color utility\n if (NON_COLOR_UTILITIES.has(value)) {\n return false;\n }\n\n // Treat everything else as a potential color\n // This catches:\n // - Standard Tailwind colors: blue-500, slate-900, white, black\n // - Custom colors defined in tailwind.config: brand, primary (non-shadcn), custom-blue\n // - Arbitrary values: [#fff], [rgb(255,0,0)], [var(--my-color)]\n // - Opacity modifiers: blue-500/50, white/80\n return true;\n}\n\n/**\n * Check if a class is exempt from dark mode requirements\n */\nfunction isExempt(baseClass: string): boolean {\n return EXEMPT_SUFFIXES.some((suffix) => baseClass.endsWith(suffix));\n}\n\nexport default createRule<Options, MessageIds>({\n name: \"consistent-dark-mode\",\n meta: {\n type: \"problem\",\n docs: {\n description: \"Ensure consistent dark mode theming in Tailwind classes\",\n },\n messages: {\n inconsistentDarkMode:\n \"Inconsistent dark mode: '{{unthemed}}' lack dark: variants while other color classes have them.\",\n missingDarkMode:\n \"No dark mode theming detected. Consider adding dark: variants for color classes.\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n warnOnMissingDarkMode: {\n type: \"boolean\",\n description:\n \"Whether to warn when no dark mode classes are found in a file that uses Tailwind colors\",\n },\n },\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [{ warnOnMissingDarkMode: true }],\n create(context) {\n const options = context.options[0] || {};\n const warnOnMissingDarkMode = options.warnOnMissingDarkMode ?? true;\n\n let fileHasColorClasses = false;\n let fileHasDarkMode = false;\n const reportedNodes = new Set<TSESTree.Node>();\n\n function checkClassString(node: TSESTree.Node, classString: string) {\n const classes = classString.split(/\\s+/).filter(Boolean);\n if (classes.length === 0) return;\n\n // Track usage per color prefix: { hasLight, hasDark, lightClasses }\n const prefixUsage = new Map<\n string,\n { hasLight: boolean; hasDark: boolean; lightClasses: string[] }\n >();\n\n for (const cls of classes) {\n const baseClass = getBaseClass(cls);\n const prefix = getColorPrefix(baseClass);\n\n if (!prefix) continue;\n if (isExempt(baseClass)) continue;\n\n // Verify this is actually a color class, not something like text-lg\n if (!isColorValue(baseClass, prefix)) continue;\n\n if (!prefixUsage.has(prefix)) {\n prefixUsage.set(prefix, {\n hasLight: false,\n hasDark: false,\n lightClasses: [],\n });\n }\n\n const usage = prefixUsage.get(prefix)!;\n\n if (hasDarkVariant(cls)) {\n usage.hasDark = true;\n fileHasDarkMode = true;\n } else {\n usage.hasLight = true;\n usage.lightClasses.push(cls);\n }\n }\n\n // Track if file uses color classes\n if (prefixUsage.size > 0) {\n fileHasColorClasses = true;\n }\n\n // Check for inconsistency: some prefixes have dark variants, others don't\n const entries = Array.from(prefixUsage.entries());\n const hasSomeDark = entries.some(([_, u]) => u.hasDark);\n\n if (hasSomeDark) {\n const unthemedEntries = entries.filter(\n ([_, usage]) => usage.hasLight && !usage.hasDark\n );\n\n if (unthemedEntries.length > 0 && !reportedNodes.has(node)) {\n reportedNodes.add(node);\n // Collect the actual class names that lack dark variants\n const unthemedClasses = unthemedEntries.flatMap(\n ([_, u]) => u.lightClasses\n );\n\n context.report({\n node,\n messageId: \"inconsistentDarkMode\",\n data: { unthemed: unthemedClasses.join(\", \") },\n });\n }\n }\n }\n\n function processStringValue(node: TSESTree.Node, value: string) {\n checkClassString(node, value);\n }\n\n function processTemplateLiteral(node: TSESTree.TemplateLiteral) {\n for (const quasi of node.quasis) {\n checkClassString(quasi, quasi.value.raw);\n }\n }\n\n return {\n // Check className attributes in JSX\n JSXAttribute(node) {\n if (\n node.name.type === \"JSXIdentifier\" &&\n (node.name.name === \"className\" || node.name.name === \"class\")\n ) {\n const value = node.value;\n\n // Handle string literal: className=\"...\"\n if (value?.type === \"Literal\" && typeof value.value === \"string\") {\n processStringValue(value, value.value);\n }\n\n // Handle JSX expression: className={...}\n if (value?.type === \"JSXExpressionContainer\") {\n const expr = value.expression;\n\n // Direct string: className={\"...\"}\n if (expr.type === \"Literal\" && typeof expr.value === \"string\") {\n processStringValue(expr, expr.value);\n }\n\n // Template literal: className={`...`}\n if (expr.type === \"TemplateLiteral\") {\n processTemplateLiteral(expr);\n }\n }\n }\n },\n\n // Check cn(), clsx(), classnames(), cva() calls\n CallExpression(node) {\n if (node.callee.type !== \"Identifier\") return;\n const name = node.callee.name;\n\n if (\n name === \"cn\" ||\n name === \"clsx\" ||\n name === \"classnames\" ||\n name === \"cva\" ||\n name === \"twMerge\"\n ) {\n for (const arg of node.arguments) {\n if (arg.type === \"Literal\" && typeof arg.value === \"string\") {\n processStringValue(arg, arg.value);\n }\n if (arg.type === \"TemplateLiteral\") {\n processTemplateLiteral(arg);\n }\n // Handle arrays of class strings\n if (arg.type === \"ArrayExpression\") {\n for (const element of arg.elements) {\n if (\n element?.type === \"Literal\" &&\n typeof element.value === \"string\"\n ) {\n processStringValue(element, element.value);\n }\n if (element?.type === \"TemplateLiteral\") {\n processTemplateLiteral(element);\n }\n }\n }\n }\n }\n },\n\n // At the end of the file, check if Tailwind colors are used without any dark mode\n \"Program:exit\"(node) {\n if (warnOnMissingDarkMode && fileHasColorClasses && !fileHasDarkMode) {\n context.report({\n node,\n messageId: \"missingDarkMode\",\n });\n }\n },\n };\n },\n});\n","/**\n * Rule: no-direct-store-import\n *\n * Forbids direct Zustand store imports - prefer using hooks via context.\n */\n\nimport { createRule } from \"../utils/create-rule.js\";\n\ntype MessageIds = \"noDirectImport\";\ntype Options = [\n {\n storePattern?: string;\n }\n];\n\n// Convert glob pattern to regex\nfunction patternToRegex(pattern: string): RegExp {\n const escaped = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*/g, \".*\")\n .replace(/\\?/g, \".\");\n return new RegExp(`^${escaped}$`);\n}\n\nexport default createRule<Options, MessageIds>({\n name: \"no-direct-store-import\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Forbid direct Zustand store imports (use hooks via context)\",\n },\n messages: {\n noDirectImport:\n \"Avoid importing store '{{name}}' directly. Use the store via a context hook instead.\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n storePattern: {\n type: \"string\",\n description: \"Glob pattern for store names\",\n },\n },\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [{ storePattern: \"use*Store\" }],\n create(context) {\n const options = context.options[0] || {};\n const pattern = options.storePattern || \"use*Store\";\n const regex = patternToRegex(pattern);\n\n return {\n ImportDeclaration(node) {\n // Check if importing from a store file\n const source = node.source.value as string;\n if (!source.includes(\"store\")) return;\n\n // Check imported specifiers\n for (const specifier of node.specifiers) {\n if (specifier.type === \"ImportSpecifier\") {\n const importedName =\n specifier.imported.type === \"Identifier\"\n ? specifier.imported.name\n : specifier.imported.value;\n\n if (regex.test(importedName)) {\n context.report({\n node: specifier,\n messageId: \"noDirectImport\",\n data: { name: importedName },\n });\n }\n }\n\n if (specifier.type === \"ImportDefaultSpecifier\") {\n const localName = specifier.local.name;\n if (regex.test(localName)) {\n context.report({\n node: specifier,\n messageId: \"noDirectImport\",\n data: { name: localName },\n });\n }\n }\n }\n },\n };\n },\n});\n","/**\n * Rule: prefer-zustand-state-management\n *\n * Detects excessive use of React state hooks (useState, useReducer, useContext)\n * in components and suggests using Zustand stores for better state management.\n */\n\nimport { createRule } from \"../utils/create-rule.js\";\nimport type { TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"excessiveStateHooks\";\ntype Options = [\n {\n /** Maximum number of state hooks before warning. Default: 3 */\n maxStateHooks?: number;\n /** Whether to count useState calls. Default: true */\n countUseState?: boolean;\n /** Whether to count useReducer calls. Default: true */\n countUseReducer?: boolean;\n /** Whether to count useContext calls. Default: true */\n countUseContext?: boolean;\n }?\n];\n\ninterface ComponentInfo {\n name: string;\n node: TSESTree.Node;\n hookCount: number;\n functionNode:\n | TSESTree.FunctionDeclaration\n | TSESTree.FunctionExpression\n | TSESTree.ArrowFunctionExpression;\n}\n\nconst STATE_HOOKS = new Set([\"useState\", \"useReducer\", \"useContext\"]);\n\nexport default createRule<Options, MessageIds>({\n name: \"prefer-zustand-state-management\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Detect excessive use of React state hooks and suggest Zustand stores\",\n },\n messages: {\n excessiveStateHooks:\n \"Component '{{component}}' has {{count}} state hooks (max: {{max}}). Consider using a Zustand store for state management.\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n maxStateHooks: {\n type: \"number\",\n minimum: 1,\n description: \"Maximum number of state hooks before warning\",\n },\n countUseState: {\n type: \"boolean\",\n description: \"Whether to count useState calls\",\n },\n countUseReducer: {\n type: \"boolean\",\n description: \"Whether to count useReducer calls\",\n },\n countUseContext: {\n type: \"boolean\",\n description: \"Whether to count useContext calls\",\n },\n },\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [\n {\n maxStateHooks: 3,\n countUseState: true,\n countUseReducer: true,\n countUseContext: true,\n },\n ],\n create(context) {\n const options = context.options[0] || {};\n const maxStateHooks = options.maxStateHooks ?? 3;\n const countUseState = options.countUseState ?? true;\n const countUseReducer = options.countUseReducer ?? true;\n const countUseContext = options.countUseContext ?? true;\n\n // Stack to track current component context\n const componentStack: ComponentInfo[] = [];\n\n // Set of function nodes we've identified as components to check\n const componentFunctions = new Map<TSESTree.Node, ComponentInfo>();\n\n /**\n * Check if a function name indicates a React component (PascalCase)\n */\n function isComponentName(name: string | null | undefined): boolean {\n if (!name) return false;\n // Components start with uppercase, hooks start with lowercase \"use\"\n return /^[A-Z]/.test(name);\n }\n\n /**\n * Check if a function name indicates a custom hook (starts with \"use\")\n */\n function isCustomHookName(name: string | null | undefined): boolean {\n if (!name) return false;\n return /^use[A-Z]/.test(name);\n }\n\n /**\n * Get the name of a function from various declaration patterns\n */\n function getFunctionName(\n node:\n | TSESTree.FunctionDeclaration\n | TSESTree.FunctionExpression\n | TSESTree.ArrowFunctionExpression\n ): string | null {\n // Function declaration: function MyComponent() {}\n if (node.type === \"FunctionDeclaration\" && node.id) {\n return node.id.name;\n }\n\n // Check parent for variable declaration: const MyComponent = () => {}\n const parent = node.parent;\n\n if (\n parent?.type === \"VariableDeclarator\" &&\n parent.id.type === \"Identifier\"\n ) {\n return parent.id.name;\n }\n\n // Check for forwardRef/memo: const MyComponent = forwardRef(function MyComponent() {})\n // or const MyComponent = forwardRef(() => {})\n if (parent?.type === \"CallExpression\") {\n const callParent = parent.parent;\n if (\n callParent?.type === \"VariableDeclarator\" &&\n callParent.id.type === \"Identifier\"\n ) {\n return callParent.id.name;\n }\n }\n\n // Named function expression: const x = function MyComponent() {}\n if (node.type === \"FunctionExpression\" && node.id) {\n return node.id.name;\n }\n\n return null;\n }\n\n /**\n * Check if a hook call should be counted based on options\n */\n function shouldCountHook(hookName: string): boolean {\n switch (hookName) {\n case \"useState\":\n return countUseState;\n case \"useReducer\":\n return countUseReducer;\n case \"useContext\":\n return countUseContext;\n default:\n return false;\n }\n }\n\n /**\n * Get hook name from a call expression (handles both useState and React.useState)\n */\n function getHookName(callee: TSESTree.Expression): string | null {\n // Direct call: useState()\n if (callee.type === \"Identifier\" && STATE_HOOKS.has(callee.name)) {\n return callee.name;\n }\n\n // Member expression: React.useState()\n if (\n callee.type === \"MemberExpression\" &&\n callee.object.type === \"Identifier\" &&\n callee.object.name === \"React\" &&\n callee.property.type === \"Identifier\" &&\n STATE_HOOKS.has(callee.property.name)\n ) {\n return callee.property.name;\n }\n\n return null;\n }\n\n /**\n * Check if we're directly inside a component function (not in a nested function)\n */\n function isDirectChildOfComponent(\n node: TSESTree.Node,\n componentNode: TSESTree.Node\n ): boolean {\n let current: TSESTree.Node | undefined = node.parent;\n\n while (current) {\n // If we hit the component node, we're a direct child\n if (current === componentNode) {\n return true;\n }\n\n // If we hit another function first, we're nested\n if (\n current.type === \"FunctionDeclaration\" ||\n current.type === \"FunctionExpression\" ||\n current.type === \"ArrowFunctionExpression\"\n ) {\n return false;\n }\n\n current = current.parent;\n }\n\n return false;\n }\n\n /**\n * Enter a function that might be a component\n */\n function enterFunction(\n node:\n | TSESTree.FunctionDeclaration\n | TSESTree.FunctionExpression\n | TSESTree.ArrowFunctionExpression\n ) {\n const name = getFunctionName(node);\n\n // Skip custom hooks - they're allowed to have many state hooks\n if (isCustomHookName(name)) {\n return;\n }\n\n // Skip non-component functions (lowercase names that aren't anonymous)\n if (name && !isComponentName(name)) {\n return;\n }\n\n // Track this as a potential component\n const componentInfo: ComponentInfo = {\n name: name || \"AnonymousComponent\",\n node,\n hookCount: 0,\n functionNode: node,\n };\n\n componentStack.push(componentInfo);\n componentFunctions.set(node, componentInfo);\n }\n\n /**\n * Exit a function and report if it had too many hooks\n */\n function exitFunction(\n node:\n | TSESTree.FunctionDeclaration\n | TSESTree.FunctionExpression\n | TSESTree.ArrowFunctionExpression\n ) {\n const componentInfo = componentFunctions.get(node);\n\n if (!componentInfo) {\n return;\n }\n\n // Remove from stack\n const index = componentStack.findIndex((c) => c.functionNode === node);\n if (index !== -1) {\n componentStack.splice(index, 1);\n }\n\n // Check if exceeded threshold\n if (componentInfo.hookCount > maxStateHooks) {\n context.report({\n node: componentInfo.node,\n messageId: \"excessiveStateHooks\",\n data: {\n component: componentInfo.name,\n count: componentInfo.hookCount,\n max: maxStateHooks,\n },\n });\n }\n\n componentFunctions.delete(node);\n }\n\n return {\n FunctionDeclaration: enterFunction,\n FunctionExpression: enterFunction,\n ArrowFunctionExpression: enterFunction,\n \"FunctionDeclaration:exit\": exitFunction,\n \"FunctionExpression:exit\": exitFunction,\n \"ArrowFunctionExpression:exit\": exitFunction,\n\n CallExpression(node) {\n const hookName = getHookName(node.callee);\n\n if (!hookName || !shouldCountHook(hookName)) {\n return;\n }\n\n // Find the innermost component this hook belongs to\n // We iterate from the end to find the most recent (innermost) component\n for (let i = componentStack.length - 1; i >= 0; i--) {\n const component = componentStack[i];\n\n if (isDirectChildOfComponent(node, component.functionNode)) {\n component.hookCount++;\n break;\n }\n }\n },\n };\n },\n});\n","/**\n * Export Resolver\n *\n * Resolves import paths and finds export definitions, following re-exports\n * to their original source files.\n */\n\nimport { ResolverFactory } from \"oxc-resolver\";\nimport { parse } from \"@typescript-eslint/typescript-estree\";\nimport { readFileSync, existsSync } from \"fs\";\nimport { dirname, join, extname } from \"path\";\nimport type { TSESTree } from \"@typescript-eslint/utils\";\n\n// Module-level resolver instance (reused across calls)\nlet resolverInstance: ReturnType<typeof ResolverFactory.prototype.sync> | null =\n null;\nlet resolverFactory: ResolverFactory | null = null;\n\n/**\n * Information about a resolved export\n */\nexport interface ResolvedExport {\n /** The name of the export (e.g., \"Button\") */\n name: string;\n /** Absolute path to the file containing the actual definition */\n filePath: string;\n /** The local name in the source file (may differ from export name) */\n localName: string;\n /** Whether this is a re-export (export { X } from './other') */\n isReexport: boolean;\n}\n\n/**\n * Cache for file exports to avoid re-parsing\n */\nconst exportCache = new Map<\n string,\n Map<string, { localName: string; reexportSource?: string }>\n>();\n\n/**\n * Cache for parsed ASTs\n */\nconst astCache = new Map<string, TSESTree.Program>();\n\n/**\n * Cache for resolved paths\n */\nconst resolvedPathCache = new Map<string, string | null>();\n\n/**\n * Get or create the resolver factory\n */\nfunction getResolverFactory(): ResolverFactory {\n if (!resolverFactory) {\n resolverFactory = new ResolverFactory({\n extensions: [\".tsx\", \".ts\", \".jsx\", \".js\"],\n mainFields: [\"module\", \"main\"],\n conditionNames: [\"import\", \"require\", \"node\", \"default\"],\n // Enable TypeScript path resolution\n tsconfig: {\n configFile: \"tsconfig.json\",\n references: \"auto\",\n },\n });\n }\n return resolverFactory;\n}\n\n/**\n * Resolve an import path to an absolute file path\n */\nexport function resolveImportPath(\n importSource: string,\n fromFile: string\n): string | null {\n const cacheKey = `${fromFile}::${importSource}`;\n\n if (resolvedPathCache.has(cacheKey)) {\n return resolvedPathCache.get(cacheKey) ?? null;\n }\n\n // Skip node_modules\n if (\n importSource.startsWith(\"react\") ||\n importSource.startsWith(\"next\") ||\n (!importSource.startsWith(\".\") &&\n !importSource.startsWith(\"@/\") &&\n !importSource.startsWith(\"~/\"))\n ) {\n // Check if it's a known external package\n if (\n importSource.includes(\"@mui/\") ||\n importSource.includes(\"@chakra-ui/\") ||\n importSource.includes(\"antd\") ||\n importSource.includes(\"@radix-ui/\")\n ) {\n // Return a marker for external packages - we don't resolve them but track them\n resolvedPathCache.set(cacheKey, null);\n return null;\n }\n resolvedPathCache.set(cacheKey, null);\n return null;\n }\n\n try {\n const factory = getResolverFactory();\n const fromDir = dirname(fromFile);\n const result = factory.sync(fromDir, importSource);\n\n if (result.path) {\n resolvedPathCache.set(cacheKey, result.path);\n return result.path;\n }\n } catch {\n // Fallback: try manual resolution for common patterns\n const resolved = manualResolve(importSource, fromFile);\n resolvedPathCache.set(cacheKey, resolved);\n return resolved;\n }\n\n resolvedPathCache.set(cacheKey, null);\n return null;\n}\n\n/**\n * Manual fallback resolution for common patterns\n */\nfunction manualResolve(importSource: string, fromFile: string): string | null {\n const fromDir = dirname(fromFile);\n const extensions = [\".tsx\", \".ts\", \".jsx\", \".js\"];\n\n // Handle @/ alias - find tsconfig and resolve\n if (importSource.startsWith(\"@/\")) {\n const projectRoot = findProjectRoot(fromFile);\n if (projectRoot) {\n const relativePath = importSource.slice(2); // Remove @/\n for (const ext of extensions) {\n const candidate = join(projectRoot, relativePath + ext);\n if (existsSync(candidate)) {\n return candidate;\n }\n // Try index file\n const indexCandidate = join(projectRoot, relativePath, `index${ext}`);\n if (existsSync(indexCandidate)) {\n return indexCandidate;\n }\n }\n }\n }\n\n // Handle relative imports\n if (importSource.startsWith(\".\")) {\n for (const ext of extensions) {\n const candidate = join(fromDir, importSource + ext);\n if (existsSync(candidate)) {\n return candidate;\n }\n // Try index file\n const indexCandidate = join(fromDir, importSource, `index${ext}`);\n if (existsSync(indexCandidate)) {\n return indexCandidate;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Find the project root by looking for tsconfig.json or package.json\n */\nfunction findProjectRoot(fromFile: string): string | null {\n let dir = dirname(fromFile);\n const root = \"/\";\n\n while (dir !== root) {\n if (existsSync(join(dir, \"tsconfig.json\"))) {\n return dir;\n }\n if (existsSync(join(dir, \"package.json\"))) {\n return dir;\n }\n dir = dirname(dir);\n }\n\n return null;\n}\n\n/**\n * Parse a file and cache the AST\n */\nexport function parseFile(filePath: string): TSESTree.Program | null {\n if (astCache.has(filePath)) {\n return astCache.get(filePath)!;\n }\n\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const ast = parse(content, {\n jsx: true,\n loc: true,\n range: true,\n });\n astCache.set(filePath, ast);\n return ast;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract export information from a file\n */\nfunction extractExports(\n filePath: string\n): Map<string, { localName: string; reexportSource?: string }> {\n if (exportCache.has(filePath)) {\n return exportCache.get(filePath)!;\n }\n\n const exports = new Map<\n string,\n { localName: string; reexportSource?: string }\n >();\n const ast = parseFile(filePath);\n\n if (!ast) {\n exportCache.set(filePath, exports);\n return exports;\n }\n\n for (const node of ast.body) {\n // Handle: export function Button() {}\n if (\n node.type === \"ExportNamedDeclaration\" &&\n node.declaration?.type === \"FunctionDeclaration\" &&\n node.declaration.id\n ) {\n exports.set(node.declaration.id.name, {\n localName: node.declaration.id.name,\n });\n }\n\n // Handle: export const Button = () => {}\n if (\n node.type === \"ExportNamedDeclaration\" &&\n node.declaration?.type === \"VariableDeclaration\"\n ) {\n for (const decl of node.declaration.declarations) {\n if (decl.id.type === \"Identifier\") {\n exports.set(decl.id.name, { localName: decl.id.name });\n }\n }\n }\n\n // Handle: export { Button } or export { Button as Btn }\n if (node.type === \"ExportNamedDeclaration\" && node.specifiers.length > 0) {\n const source = node.source?.value as string | undefined;\n for (const spec of node.specifiers) {\n if (spec.type === \"ExportSpecifier\") {\n const exportedName =\n spec.exported.type === \"Identifier\"\n ? spec.exported.name\n : spec.exported.value;\n const localName =\n spec.local.type === \"Identifier\"\n ? spec.local.name\n : spec.local.value;\n\n exports.set(exportedName, {\n localName,\n reexportSource: source,\n });\n }\n }\n }\n\n // Handle: export default function Button() {}\n if (\n node.type === \"ExportDefaultDeclaration\" &&\n node.declaration.type === \"FunctionDeclaration\" &&\n node.declaration.id\n ) {\n exports.set(\"default\", { localName: node.declaration.id.name });\n }\n\n // Handle: export default Button\n if (\n node.type === \"ExportDefaultDeclaration\" &&\n node.declaration.type === \"Identifier\"\n ) {\n exports.set(\"default\", { localName: node.declaration.name });\n }\n }\n\n exportCache.set(filePath, exports);\n return exports;\n}\n\n/**\n * Resolve an export to its original definition, following re-exports\n */\nexport function resolveExport(\n exportName: string,\n filePath: string,\n visited = new Set<string>()\n): ResolvedExport | null {\n // Cycle detection\n const key = `${filePath}::${exportName}`;\n if (visited.has(key)) {\n return null;\n }\n visited.add(key);\n\n const exports = extractExports(filePath);\n const exportInfo = exports.get(exportName);\n\n if (!exportInfo) {\n return null;\n }\n\n // If it's a re-export, follow the chain\n if (exportInfo.reexportSource) {\n const resolvedPath = resolveImportPath(exportInfo.reexportSource, filePath);\n if (resolvedPath) {\n return resolveExport(exportInfo.localName, resolvedPath, visited);\n }\n return null;\n }\n\n // This is the actual definition\n return {\n name: exportName,\n filePath,\n localName: exportInfo.localName,\n isReexport: false,\n };\n}\n\n/**\n * Clear all caches (useful for testing or watch mode)\n */\nexport function clearResolverCaches(): void {\n exportCache.clear();\n astCache.clear();\n resolvedPathCache.clear();\n}\n","/**\n * Component Parser\n *\n * Parses a single component's body to extract styling information\n * and identify nested component usage.\n */\n\nimport type { TSESTree } from \"@typescript-eslint/utils\";\nimport { parseFile } from \"./export-resolver.js\";\n\n/**\n * Known UI library import patterns\n */\nexport type LibraryName = \"shadcn\" | \"mui\" | \"chakra\" | \"antd\";\n\nexport const LIBRARY_PATTERNS: Record<LibraryName, string[]> = {\n shadcn: [\"@/components/ui\", \"@radix-ui/\", \"components/ui/\"],\n mui: [\"@mui/material\", \"@mui/icons-material\", \"@emotion/\"],\n chakra: [\"@chakra-ui/\"],\n antd: [\"antd\", \"@ant-design/\"],\n};\n\n/**\n * Information about a component used within another component\n */\nexport interface UsedComponent {\n /** Component name (e.g., \"Button\", \"Card\") */\n name: string;\n /** Import source path (e.g., \"@mui/material\", \"./button\") */\n importSource: string;\n /** Line number where the component is used */\n line: number;\n /** Column number where the component is used */\n column: number;\n}\n\n/**\n * Styling information extracted from a component\n */\nexport interface ComponentStyleInfo {\n /** Tailwind classes used in the component */\n tailwindClasses: string[];\n /** Inline style objects (as string representations) */\n inlineStyles: string[];\n /** Other components used within this component */\n usedComponents: UsedComponent[];\n /** Directly detected library (from import source) */\n directLibrary: LibraryName | null;\n}\n\n/**\n * Import map for a file: localName -> importSource\n */\nexport type ImportMap = Map<string, string>;\n\n/**\n * Extract imports from a file's AST\n */\nexport function extractImports(ast: TSESTree.Program): ImportMap {\n const imports = new Map<string, string>();\n\n for (const node of ast.body) {\n if (node.type === \"ImportDeclaration\") {\n const source = node.source.value as string;\n for (const spec of node.specifiers) {\n if (spec.type === \"ImportSpecifier\") {\n imports.set(spec.local.name, source);\n } else if (spec.type === \"ImportDefaultSpecifier\") {\n imports.set(spec.local.name, source);\n } else if (spec.type === \"ImportNamespaceSpecifier\") {\n imports.set(spec.local.name, source);\n }\n }\n }\n }\n\n return imports;\n}\n\n/**\n * Detect which UI library an import source belongs to\n */\nexport function detectLibraryFromSource(\n importSource: string\n): LibraryName | null {\n for (const [library, patterns] of Object.entries(LIBRARY_PATTERNS)) {\n if (patterns.some((p) => importSource.includes(p))) {\n return library as LibraryName;\n }\n }\n return null;\n}\n\n/**\n * Find a function/arrow function component definition by name in an AST\n */\nexport function findComponentDefinition(\n ast: TSESTree.Program,\n componentName: string\n): TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression | null {\n for (const node of ast.body) {\n // export function ComponentName() {}\n if (\n node.type === \"ExportNamedDeclaration\" &&\n node.declaration?.type === \"FunctionDeclaration\" &&\n node.declaration.id?.name === componentName\n ) {\n return node.declaration;\n }\n\n // export const ComponentName = () => {}\n if (\n node.type === \"ExportNamedDeclaration\" &&\n node.declaration?.type === \"VariableDeclaration\"\n ) {\n for (const decl of node.declaration.declarations) {\n if (\n decl.id.type === \"Identifier\" &&\n decl.id.name === componentName &&\n decl.init?.type === \"ArrowFunctionExpression\"\n ) {\n return decl.init;\n }\n }\n }\n\n // function ComponentName() {} (not exported directly)\n if (\n node.type === \"FunctionDeclaration\" &&\n node.id?.name === componentName\n ) {\n return node;\n }\n\n // const ComponentName = () => {}\n if (node.type === \"VariableDeclaration\") {\n for (const decl of node.declarations) {\n if (\n decl.id.type === \"Identifier\" &&\n decl.id.name === componentName &&\n decl.init?.type === \"ArrowFunctionExpression\"\n ) {\n return decl.init;\n }\n }\n }\n\n // export default function ComponentName() {}\n if (\n node.type === \"ExportDefaultDeclaration\" &&\n node.declaration.type === \"FunctionDeclaration\" &&\n node.declaration.id?.name === componentName\n ) {\n return node.declaration;\n }\n }\n\n return null;\n}\n\n/**\n * Extract Tailwind classes from a className string\n */\nfunction extractTailwindClasses(classString: string): string[] {\n return classString.split(/\\s+/).filter(Boolean);\n}\n\n/**\n * Recursively traverse a node and extract styling info\n */\nfunction traverseForStyling(\n node: TSESTree.Node,\n imports: ImportMap,\n result: ComponentStyleInfo\n): void {\n if (!node || typeof node !== \"object\") return;\n\n // Handle JSX elements\n if (node.type === \"JSXElement\" && node.openingElement) {\n const opening = node.openingElement;\n\n // Check if this is a component (PascalCase) or HTML element\n if (\n opening.name.type === \"JSXIdentifier\" &&\n /^[A-Z]/.test(opening.name.name)\n ) {\n const componentName = opening.name.name;\n const importSource = imports.get(componentName);\n\n if (importSource) {\n result.usedComponents.push({\n name: componentName,\n importSource,\n line: opening.loc.start.line,\n column: opening.loc.start.column,\n });\n\n // Check if this import is from a known UI library\n const library = detectLibraryFromSource(importSource);\n if (library && !result.directLibrary) {\n result.directLibrary = library;\n }\n }\n }\n\n // Handle JSX member expressions like Modal.Header\n if (opening.name.type === \"JSXMemberExpression\") {\n let objectName: string | null = null;\n let current = opening.name.object;\n while (current.type === \"JSXMemberExpression\") {\n current = current.object;\n }\n if (current.type === \"JSXIdentifier\") {\n objectName = current.name;\n }\n\n if (objectName) {\n const importSource = imports.get(objectName);\n if (importSource) {\n const library = detectLibraryFromSource(importSource);\n if (library && !result.directLibrary) {\n result.directLibrary = library;\n }\n }\n }\n }\n\n // Extract className/class attributes\n for (const attr of opening.attributes) {\n if (\n attr.type === \"JSXAttribute\" &&\n attr.name.type === \"JSXIdentifier\" &&\n (attr.name.name === \"className\" || attr.name.name === \"class\")\n ) {\n if (\n attr.value?.type === \"Literal\" &&\n typeof attr.value.value === \"string\"\n ) {\n result.tailwindClasses.push(\n ...extractTailwindClasses(attr.value.value)\n );\n }\n if (attr.value?.type === \"JSXExpressionContainer\") {\n const expr = attr.value.expression;\n if (expr.type === \"Literal\" && typeof expr.value === \"string\") {\n result.tailwindClasses.push(...extractTailwindClasses(expr.value));\n }\n if (expr.type === \"TemplateLiteral\") {\n for (const quasi of expr.quasis) {\n result.tailwindClasses.push(\n ...extractTailwindClasses(quasi.value.raw)\n );\n }\n }\n }\n }\n\n // Extract inline styles\n if (\n attr.type === \"JSXAttribute\" &&\n attr.name.type === \"JSXIdentifier\" &&\n attr.name.name === \"style\"\n ) {\n if (attr.value?.type === \"JSXExpressionContainer\") {\n // Just note that there's an inline style - we don't parse the object\n result.inlineStyles.push(\"[inline style]\");\n }\n }\n }\n }\n\n // Handle cn(), clsx(), twMerge() calls\n if (\n node.type === \"CallExpression\" &&\n node.callee.type === \"Identifier\" &&\n [\"cn\", \"clsx\", \"classnames\", \"twMerge\"].includes(node.callee.name)\n ) {\n for (const arg of node.arguments) {\n if (arg.type === \"Literal\" && typeof arg.value === \"string\") {\n result.tailwindClasses.push(...extractTailwindClasses(arg.value));\n }\n if (arg.type === \"TemplateLiteral\") {\n for (const quasi of arg.quasis) {\n result.tailwindClasses.push(\n ...extractTailwindClasses(quasi.value.raw)\n );\n }\n }\n }\n }\n\n // Recursively traverse all properties\n for (const key of Object.keys(node)) {\n if (key === \"parent\" || key === \"loc\" || key === \"range\") continue;\n\n const child = (node as unknown as Record<string, unknown>)[key];\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === \"object\") {\n traverseForStyling(item as TSESTree.Node, imports, result);\n }\n }\n } else if (child && typeof child === \"object\") {\n traverseForStyling(child as TSESTree.Node, imports, result);\n }\n }\n}\n\n/**\n * Parse a component's body and extract styling information\n */\nexport function parseComponentBody(\n filePath: string,\n componentName: string\n): ComponentStyleInfo | null {\n const ast = parseFile(filePath);\n if (!ast) return null;\n\n const imports = extractImports(ast);\n const componentDef = findComponentDefinition(ast, componentName);\n\n if (!componentDef) {\n return null;\n }\n\n const result: ComponentStyleInfo = {\n tailwindClasses: [],\n inlineStyles: [],\n usedComponents: [],\n directLibrary: null,\n };\n\n // Traverse the component body\n if (componentDef.body) {\n traverseForStyling(componentDef.body, imports, result);\n }\n\n // Deduplicate classes\n result.tailwindClasses = [...new Set(result.tailwindClasses)];\n\n return result;\n}\n\n/**\n * Analyze a file and extract all component usages with their libraries\n * (used for the entry file analysis)\n */\nexport function analyzeFileImports(\n filePath: string\n): Map<string, { importSource: string; library: LibraryName | null }> {\n const ast = parseFile(filePath);\n if (!ast) return new Map();\n\n const result = new Map<\n string,\n { importSource: string; library: LibraryName | null }\n >();\n const imports = extractImports(ast);\n\n for (const [name, source] of imports) {\n result.set(name, {\n importSource: source,\n library: detectLibraryFromSource(source),\n });\n }\n\n return result;\n}\n","/**\n * Import Graph Service\n *\n * Provides demand-driven cross-file analysis to detect UI library usage\n * across component trees. Uses in-memory caching for performance.\n */\n\nimport {\n resolveImportPath,\n resolveExport,\n clearResolverCaches,\n} from \"./export-resolver.js\";\nimport {\n parseComponentBody,\n detectLibraryFromSource,\n type LibraryName,\n type ComponentStyleInfo,\n} from \"./component-parser.js\";\n\n/**\n * Information about a component's UI library usage\n */\nexport interface ComponentLibraryInfo {\n /** Direct library (from import source, e.g., \"@mui/material\" -> \"mui\") */\n library: LibraryName | null;\n /** Libraries used internally by this component (for local components) */\n internalLibraries: Set<LibraryName>;\n /** Evidence of which internal components caused the library detection */\n libraryEvidence: Array<{\n componentName: string;\n library: LibraryName;\n }>;\n /** Whether this is a local component (resolved from project files) */\n isLocalComponent: boolean;\n}\n\n/**\n * Cache for analyzed components: \"filePath::componentName\" -> ComponentLibraryInfo\n */\nconst componentLibraryCache = new Map<string, ComponentLibraryInfo>();\n\n/**\n * Get a singleton instance of the import graph service\n */\nexport function getImportGraphService() {\n return {\n getComponentLibrary,\n clearCache,\n };\n}\n\n/**\n * Analyze a component's library usage, including transitive dependencies\n *\n * @param contextFilePath - The file where the component is used (for resolving relative imports)\n * @param componentName - The name of the component (e.g., \"Button\", \"MyCard\")\n * @param importSource - The import source (e.g., \"@mui/material\", \"./components/cards\")\n * @returns Library information including direct and transitive library usage\n */\nexport function getComponentLibrary(\n contextFilePath: string,\n componentName: string,\n importSource: string\n): ComponentLibraryInfo {\n // Check if import source directly indicates a known library\n const directLibrary = detectLibraryFromSource(importSource);\n\n if (directLibrary) {\n // It's a direct import from a known library (e.g., @mui/material)\n return {\n library: directLibrary,\n internalLibraries: new Set(),\n libraryEvidence: [],\n isLocalComponent: false,\n };\n }\n\n // It's a local component - resolve and analyze it\n const resolvedPath = resolveImportPath(importSource, contextFilePath);\n\n if (!resolvedPath) {\n // Could not resolve - might be external or invalid\n return {\n library: null,\n internalLibraries: new Set(),\n libraryEvidence: [],\n isLocalComponent: false,\n };\n }\n\n // Check cache\n const cacheKey = `${resolvedPath}::${componentName}`;\n if (componentLibraryCache.has(cacheKey)) {\n return componentLibraryCache.get(cacheKey)!;\n }\n\n // Resolve re-exports to find the actual component definition\n const resolvedExport = resolveExport(componentName, resolvedPath);\n const actualFilePath = resolvedExport?.filePath ?? resolvedPath;\n const actualComponentName = resolvedExport?.localName ?? componentName;\n\n // Analyze the component body\n const result = analyzeComponentLibraries(\n actualFilePath,\n actualComponentName,\n new Set([cacheKey]) // Track visited to prevent cycles\n );\n\n componentLibraryCache.set(cacheKey, result);\n return result;\n}\n\n/**\n * Recursively analyze a component's library usage\n */\nfunction analyzeComponentLibraries(\n filePath: string,\n componentName: string,\n visited: Set<string>\n): ComponentLibraryInfo {\n const styleInfo = parseComponentBody(filePath, componentName);\n\n if (!styleInfo) {\n return {\n library: null,\n internalLibraries: new Set(),\n libraryEvidence: [],\n isLocalComponent: true,\n };\n }\n\n const internalLibraries = new Set<LibraryName>();\n const libraryEvidence: Array<{ componentName: string; library: LibraryName }> = [];\n\n // Check direct library usage within this component\n if (styleInfo.directLibrary) {\n internalLibraries.add(styleInfo.directLibrary);\n }\n\n // Analyze each used component\n for (const usedComponent of styleInfo.usedComponents) {\n const usedLibrary = detectLibraryFromSource(usedComponent.importSource);\n\n if (usedLibrary) {\n // Direct import from a known library\n internalLibraries.add(usedLibrary);\n libraryEvidence.push({\n componentName: usedComponent.name,\n library: usedLibrary,\n });\n } else {\n // It's a local component - recurse into it\n const resolvedPath = resolveImportPath(usedComponent.importSource, filePath);\n\n if (resolvedPath) {\n const cacheKey = `${resolvedPath}::${usedComponent.name}`;\n\n // Skip if already visited (cycle detection)\n if (!visited.has(cacheKey)) {\n visited.add(cacheKey);\n\n // Check cache first\n let nestedInfo: ComponentLibraryInfo;\n if (componentLibraryCache.has(cacheKey)) {\n nestedInfo = componentLibraryCache.get(cacheKey)!;\n } else {\n // Resolve re-exports\n const resolvedExport = resolveExport(usedComponent.name, resolvedPath);\n const actualFilePath = resolvedExport?.filePath ?? resolvedPath;\n const actualComponentName = resolvedExport?.localName ?? usedComponent.name;\n\n nestedInfo = analyzeComponentLibraries(\n actualFilePath,\n actualComponentName,\n visited\n );\n componentLibraryCache.set(cacheKey, nestedInfo);\n }\n\n // Aggregate the nested component's libraries\n if (nestedInfo.library) {\n internalLibraries.add(nestedInfo.library);\n libraryEvidence.push({\n componentName: usedComponent.name,\n library: nestedInfo.library,\n });\n }\n\n for (const lib of nestedInfo.internalLibraries) {\n internalLibraries.add(lib);\n }\n\n // Add evidence from nested components\n for (const evidence of nestedInfo.libraryEvidence) {\n libraryEvidence.push({\n componentName: `${usedComponent.name} → ${evidence.componentName}`,\n library: evidence.library,\n });\n }\n }\n }\n }\n }\n\n return {\n library: styleInfo.directLibrary,\n internalLibraries,\n libraryEvidence,\n isLocalComponent: true,\n };\n}\n\n/**\n * Clear all caches (useful for testing or between ESLint runs)\n */\nexport function clearCache(): void {\n componentLibraryCache.clear();\n clearResolverCaches();\n}\n\n// Re-export types for convenience\nexport type { LibraryName };\n","/**\n * Rule: no-mixed-component-libraries\n *\n * Forbids using non-preferred UI component libraries. Reports errors at\n * the JSX usage site, including transitive usage through local components.\n *\n * Examples:\n * - <MuiButton> from @mui/material -> error at <MuiButton> usage\n * - <MyCard> that internally uses MUI -> error at <MyCard> usage\n */\n\nimport type { TSESTree } from \"@typescript-eslint/utils\";\nimport { createRule } from \"../utils/create-rule.js\";\nimport {\n getComponentLibrary,\n type LibraryName,\n} from \"../utils/import-graph.js\";\n\ntype MessageIds = \"nonPreferredLibrary\" | \"transitiveNonPreferred\";\ntype Options = [\n {\n /** The preferred UI library. Components from other libraries will be flagged. */\n preferred: LibraryName;\n /** Additional libraries to detect (defaults to common ones) */\n libraries?: LibraryName[];\n }\n];\n\n/**\n * Information about a component usage in the file\n */\ninterface ComponentUsage {\n /** The JSX element node (for error reporting) */\n node: TSESTree.JSXOpeningElement;\n /** Component name (e.g., \"Button\", \"MuiCard\") */\n componentName: string;\n /** Import source (e.g., \"@mui/material\", \"./components/cards\") */\n importSource: string;\n}\n\nexport default createRule<Options, MessageIds>({\n name: \"no-mixed-component-libraries\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Forbid using non-preferred UI component libraries. Reports at JSX usage sites, including transitive usage.\",\n },\n messages: {\n nonPreferredLibrary:\n \"Component <{{component}}> is from {{library}}, but {{preferred}} is the preferred library.\",\n transitiveNonPreferred:\n \"Component <{{component}}> internally uses {{libraries}} components ({{internalComponents}}). The preferred library is {{preferred}}.\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n preferred: {\n type: \"string\",\n enum: [\"shadcn\", \"mui\", \"chakra\", \"antd\"],\n description: \"The preferred UI library\",\n },\n libraries: {\n type: \"array\",\n items: {\n type: \"string\",\n enum: [\"shadcn\", \"mui\", \"chakra\", \"antd\"],\n },\n description: \"Libraries to detect (defaults to all)\",\n },\n },\n required: [\"preferred\"],\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [\n { preferred: \"shadcn\", libraries: [\"shadcn\", \"mui\", \"chakra\", \"antd\"] },\n ],\n create(context) {\n const options = context.options[0];\n const preferred = options.preferred;\n\n // Track imports: localName -> importSource\n const importMap = new Map<string, string>();\n\n // Track all component usages for analysis at Program:exit\n const componentUsages: ComponentUsage[] = [];\n\n return {\n ImportDeclaration(node) {\n const source = node.source.value as string;\n\n for (const spec of node.specifiers) {\n if (spec.type === \"ImportSpecifier\") {\n importMap.set(spec.local.name, source);\n } else if (spec.type === \"ImportDefaultSpecifier\") {\n importMap.set(spec.local.name, source);\n } else if (spec.type === \"ImportNamespaceSpecifier\") {\n importMap.set(spec.local.name, source);\n }\n }\n },\n\n JSXOpeningElement(node) {\n // Get the component name\n let componentName: string | null = null;\n\n if (node.name.type === \"JSXIdentifier\") {\n componentName = node.name.name;\n } else if (node.name.type === \"JSXMemberExpression\") {\n // Handle Namespace.Component (e.g., Modal.Header)\n let current = node.name.object;\n while (current.type === \"JSXMemberExpression\") {\n current = current.object;\n }\n if (current.type === \"JSXIdentifier\") {\n componentName = current.name;\n }\n }\n\n // Skip HTML elements (lowercase) and missing names\n if (!componentName || !/^[A-Z]/.test(componentName)) {\n return;\n }\n\n // Skip components that aren't imported (might be defined in same file)\n const importSource = importMap.get(componentName);\n if (!importSource) {\n return;\n }\n\n componentUsages.push({\n node,\n componentName,\n importSource,\n });\n },\n\n \"Program:exit\"() {\n const filename = context.filename || context.getFilename();\n\n for (const usage of componentUsages) {\n const libraryInfo = getComponentLibrary(\n filename,\n usage.componentName,\n usage.importSource\n );\n\n // Case 1: Direct import from non-preferred library\n if (libraryInfo.library && libraryInfo.library !== preferred) {\n context.report({\n node: usage.node,\n messageId: \"nonPreferredLibrary\",\n data: {\n component: usage.componentName,\n library: libraryInfo.library,\n preferred,\n },\n });\n continue;\n }\n\n // Case 2: Local component that uses non-preferred library internally\n if (\n libraryInfo.isLocalComponent &&\n libraryInfo.internalLibraries.size > 0\n ) {\n const nonPreferredLibs = [...libraryInfo.internalLibraries].filter(\n (lib) => lib !== preferred\n );\n\n if (nonPreferredLibs.length > 0) {\n // Get evidence of which internal components caused the violation\n const internalComponents = libraryInfo.libraryEvidence\n .filter((e) => e.library !== preferred)\n .map((e) => e.componentName)\n .slice(0, 3) // Limit to first 3 for readability\n .join(\", \");\n\n context.report({\n node: usage.node,\n messageId: \"transitiveNonPreferred\",\n data: {\n component: usage.componentName,\n libraries: nonPreferredLibs.join(\", \"),\n internalComponents: internalComponents || \"unknown\",\n preferred,\n },\n });\n }\n }\n }\n },\n };\n },\n});\n","/**\n * Rule: semantic\n *\n * LLM-powered semantic UI analysis using the project's styleguide.\n * This is the only rule that reads .uilint/styleguide.md.\n */\n\nimport { existsSync, readFileSync } from \"fs\";\nimport { spawnSync } from \"child_process\";\nimport { dirname, join, relative } from \"path\";\nimport { createRule } from \"../utils/create-rule.js\";\nimport {\n getCacheEntry,\n hashContentSync,\n setCacheEntry,\n type CachedIssue,\n} from \"../utils/cache.js\";\nimport { getStyleguide } from \"../utils/styleguide-loader.js\";\nimport { UILINT_DEFAULT_OLLAMA_MODEL } from \"uilint-core\";\nimport { buildSourceScanPrompt } from \"uilint-core\";\n\ntype MessageIds = \"semanticIssue\" | \"styleguideNotFound\" | \"analysisError\";\ntype Options = [\n {\n model?: string;\n styleguidePath?: string;\n }\n];\n\nexport default createRule<Options, MessageIds>({\n name: \"semantic\",\n meta: {\n type: \"suggestion\",\n docs: {\n description: \"LLM-powered semantic UI analysis using styleguide\",\n },\n messages: {\n semanticIssue: \"{{message}}\",\n styleguideNotFound:\n \"No styleguide found. Create .uilint/styleguide.md or specify styleguidePath.\",\n analysisError: \"Semantic analysis failed: {{error}}\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n model: {\n type: \"string\",\n description: \"Ollama model to use\",\n },\n styleguidePath: {\n type: \"string\",\n description: \"Path to styleguide file\",\n },\n },\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [{ model: UILINT_DEFAULT_OLLAMA_MODEL }],\n create(context) {\n const options = context.options[0] || {};\n const filePath = context.filename;\n const fileDir = dirname(filePath);\n\n // Get styleguide\n const { path: styleguidePath, content: styleguide } = getStyleguide(\n fileDir,\n options.styleguidePath\n );\n\n // Skip if no styleguide\n if (!styleguide) {\n console.error(\n `[uilint] Styleguide not found (styleguidePath=${String(\n options.styleguidePath ?? \"\"\n )}, startDir=${fileDir})`\n );\n\n return {\n Program(node) {\n context.report({\n node,\n messageId: \"styleguideNotFound\",\n });\n },\n };\n }\n\n // Read and hash file contents\n let fileContent: string;\n try {\n fileContent = readFileSync(filePath, \"utf-8\");\n } catch {\n console.error(`[uilint] Failed to read file ${filePath}`);\n return {\n Program(node) {\n context.report({\n node,\n messageId: \"analysisError\",\n data: { error: `Failed to read source file ${filePath}` },\n });\n },\n };\n }\n\n const fileHash = hashContentSync(fileContent);\n const styleguideHash = hashContentSync(styleguide);\n\n // Check cache\n const projectRoot = findProjectRoot(fileDir);\n const relativeFilePath = relative(projectRoot, filePath);\n const cached = getCacheEntry(\n projectRoot,\n relativeFilePath,\n fileHash,\n styleguideHash\n );\n\n const ENABLE_CACHE = false;\n if (ENABLE_CACHE && cached) {\n console.error(`[uilint] Cache hit for ${filePath}`);\n\n // Report cached issues\n return {\n Program(node) {\n for (const issue of cached.issues) {\n context.report({\n node,\n loc: { line: issue.line, column: issue.column || 0 },\n messageId: \"semanticIssue\",\n data: { message: issue.message },\n });\n }\n },\n };\n }\n\n // Cache miss: run sync analysis now (slow), cache, then report.\n ENABLE_CACHE &&\n console.error(\n `[uilint] Cache miss for ${filePath}, running semantic analysis`\n );\n\n return {\n Program(node) {\n const issues = runSemanticAnalysisSync(\n fileContent,\n styleguide,\n options.model || UILINT_DEFAULT_OLLAMA_MODEL,\n filePath\n );\n\n setCacheEntry(projectRoot, relativeFilePath, {\n fileHash,\n styleguideHash,\n issues,\n timestamp: Date.now(),\n });\n\n for (const issue of issues) {\n context.report({\n node,\n loc: { line: issue.line, column: issue.column || 0 },\n messageId: \"semanticIssue\",\n data: { message: issue.message },\n });\n }\n },\n };\n },\n});\n\n/**\n * Find project root by looking for package.json\n */\nfunction findProjectRoot(startDir: string): string {\n let dir = startDir;\n for (let i = 0; i < 20; i++) {\n if (existsSync(join(dir, \"package.json\"))) {\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return startDir;\n}\n\n/**\n * Run semantic analysis using Ollama (synchronously).\n *\n * Implementation detail:\n * - ESLint rules are synchronous.\n * - Blocking on a Promise (sleep-loop/Atomics) would also block Node's event loop,\n * preventing the HTTP request to Ollama from ever completing.\n * - To keep this simple & debuggable, we run the async LLM call in a child Node\n * process and synchronously wait for it to exit.\n */\nfunction runSemanticAnalysisSync(\n sourceCode: string,\n styleguide: string,\n model: string,\n filePath?: string\n): CachedIssue[] {\n const startTime = Date.now();\n const fileDisplay = filePath ? ` ${filePath}` : \"\";\n\n console.error(`[uilint] Starting semantic analysis (sync)${fileDisplay}`);\n console.error(`[uilint] Model: ${model}`);\n\n // Build prompt in-process (pure string building).\n const prompt = buildSourceScanPrompt(sourceCode, styleguide, {});\n\n // Avoid `uilint-core/node` exports *and* CJS resolution:\n // resolve the installed dependency by file URL relative to this plugin bundle.\n // When built, `import.meta.url` points at `.../uilint-eslint/dist/index.js`,\n // and the dependency lives at `.../uilint-eslint/node_modules/uilint-core/dist/node.js`.\n const coreNodeUrl = new URL(\n \"../node_modules/uilint-core/dist/node.js\",\n import.meta.url\n ).href;\n\n const childScript = `\n import * as coreNode from ${JSON.stringify(coreNodeUrl)};\n const { OllamaClient, logInfo, logWarning, createProgress, pc } = coreNode;\n const chunks = [];\n for await (const c of process.stdin) chunks.push(c);\n const input = JSON.parse(Buffer.concat(chunks).toString(\"utf8\"));\n const model = input.model;\n const prompt = input.prompt;\n\n const client = new OllamaClient({ model });\n const ok = await client.isAvailable();\n if (!ok) {\n logWarning(\"Ollama not available, skipping semantic analysis\");\n process.stdout.write(JSON.stringify({ issues: [] }));\n process.exit(0);\n }\n\n logInfo(\\`Ollama connected \\${pc.dim(\\`(model: \\${model})\\`)}\\`);\n const progress = createProgress(\"Analyzing with LLM...\");\n try {\n const response = await client.complete(prompt, {\n json: true,\n stream: true,\n onProgress: (latestLine) => {\n const maxLen = 60;\n const display =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n progress.update(\\`LLM: \\${pc.dim(display || \"...\")}\\`);\n },\n });\n progress.succeed(\"LLM complete\");\n process.stdout.write(response);\n } catch (e) {\n progress.fail(\\`LLM failed: \\${e instanceof Error ? e.message : String(e)}\\`);\n process.exit(1);\n }\n `;\n\n const child = spawnSync(\n process.execPath,\n [\"--input-type=module\", \"-e\", childScript],\n {\n input: JSON.stringify({ model, prompt }),\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"inherit\"],\n maxBuffer: 20 * 1024 * 1024,\n }\n );\n\n const elapsed = Date.now() - startTime;\n\n if (child.error) {\n console.error(\n `[uilint] Semantic analysis failed after ${elapsed}ms: ${child.error.message}`\n );\n return [];\n }\n\n if (typeof child.status === \"number\" && child.status !== 0) {\n console.error(\n `[uilint] Semantic analysis failed after ${elapsed}ms: child exited ${child.status}`\n );\n return [];\n }\n\n const responseText = (child.stdout || \"\").trim();\n if (!responseText) {\n console.error(\n `[uilint] Semantic analysis returned empty response (${elapsed}ms)`\n );\n return [];\n }\n\n try {\n const parsed = JSON.parse(responseText) as {\n issues?: Array<{ line?: number; column?: number; message?: string }>;\n };\n\n const issues = (parsed.issues || []).map((issue) => ({\n line: issue.line || 1,\n column: issue.column,\n message: issue.message || \"Semantic issue detected\",\n ruleId: \"uilint/semantic\",\n severity: 1 as const,\n }));\n\n if (issues.length > 0) {\n console.error(`[uilint] Found ${issues.length} issue(s) (${elapsed}ms)`);\n } else {\n console.error(`[uilint] No issues found (${elapsed}ms)`);\n }\n\n return issues;\n } catch (e) {\n console.error(\n `[uilint] Semantic analysis failed to parse response after ${elapsed}ms: ${\n e instanceof Error ? e.message : String(e)\n }`\n );\n return [];\n }\n}\n","/**\n * File-hash based caching for LLM semantic rule\n *\n * Uses xxhash for fast hashing of file contents.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\n\n// Lazy-loaded xxhash\nlet xxhashInstance: Awaited<\n ReturnType<typeof import(\"xxhash-wasm\")[\"default\"]>\n> | null = null;\n\nasync function getXxhash() {\n if (!xxhashInstance) {\n const xxhash = await import(\"xxhash-wasm\");\n xxhashInstance = await xxhash.default();\n }\n return xxhashInstance;\n}\n\n/**\n * Synchronous hash using a simple djb2 algorithm (fallback when xxhash not available)\n */\nfunction djb2Hash(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = (hash * 33) ^ str.charCodeAt(i);\n }\n return (hash >>> 0).toString(16);\n}\n\n/**\n * Hash content using xxhash (async) or djb2 (sync fallback)\n */\nexport async function hashContent(content: string): Promise<string> {\n try {\n const xxhash = await getXxhash();\n return xxhash.h64ToString(content);\n } catch {\n return djb2Hash(content);\n }\n}\n\n/**\n * Synchronous hash for when async is not possible\n */\nexport function hashContentSync(content: string): string {\n return djb2Hash(content);\n}\n\nexport interface CacheEntry {\n fileHash: string;\n styleguideHash: string;\n issues: CachedIssue[];\n timestamp: number;\n}\n\nexport interface CachedIssue {\n line: number;\n column?: number;\n message: string;\n ruleId: string;\n severity: 1 | 2; // 1 = warn, 2 = error\n}\n\nexport interface CacheStore {\n version: number;\n entries: Record<string, CacheEntry>;\n}\n\nconst CACHE_VERSION = 1;\nconst CACHE_FILE = \".uilint/.cache/eslint-semantic.json\";\n\n/**\n * Get the cache file path for a project\n */\nexport function getCachePath(projectRoot: string): string {\n return join(projectRoot, CACHE_FILE);\n}\n\n/**\n * Load the cache store\n */\nexport function loadCache(projectRoot: string): CacheStore {\n const cachePath = getCachePath(projectRoot);\n\n if (!existsSync(cachePath)) {\n return { version: CACHE_VERSION, entries: {} };\n }\n\n try {\n const content = readFileSync(cachePath, \"utf-8\");\n const cache = JSON.parse(content) as CacheStore;\n\n // Invalidate if version mismatch\n if (cache.version !== CACHE_VERSION) {\n return { version: CACHE_VERSION, entries: {} };\n }\n\n return cache;\n } catch {\n return { version: CACHE_VERSION, entries: {} };\n }\n}\n\n/**\n * Save the cache store\n */\nexport function saveCache(projectRoot: string, cache: CacheStore): void {\n const cachePath = getCachePath(projectRoot);\n\n try {\n const cacheDir = dirname(cachePath);\n if (!existsSync(cacheDir)) {\n mkdirSync(cacheDir, { recursive: true });\n }\n\n writeFileSync(cachePath, JSON.stringify(cache, null, 2), \"utf-8\");\n } catch {\n // Silently fail - caching is optional\n }\n}\n\n/**\n * Get cached entry for a file\n */\nexport function getCacheEntry(\n projectRoot: string,\n filePath: string,\n fileHash: string,\n styleguideHash: string\n): CacheEntry | null {\n const cache = loadCache(projectRoot);\n const entry = cache.entries[filePath];\n\n if (!entry) return null;\n\n // Check if hashes match\n if (entry.fileHash !== fileHash || entry.styleguideHash !== styleguideHash) {\n return null;\n }\n\n return entry;\n}\n\n/**\n * Set cached entry for a file\n */\nexport function setCacheEntry(\n projectRoot: string,\n filePath: string,\n entry: CacheEntry\n): void {\n const cache = loadCache(projectRoot);\n cache.entries[filePath] = entry;\n saveCache(projectRoot, cache);\n}\n\n/**\n * Clear cache for a specific file\n */\nexport function clearCacheEntry(projectRoot: string, filePath: string): void {\n const cache = loadCache(projectRoot);\n delete cache.entries[filePath];\n saveCache(projectRoot, cache);\n}\n\n/**\n * Clear entire cache\n */\nexport function clearCache(projectRoot: string): void {\n saveCache(projectRoot, { version: CACHE_VERSION, entries: {} });\n}\n","/**\n * Styleguide loader for the LLM semantic rule\n *\n * Only the semantic rule reads the styleguide - static rules use ESLint options.\n */\n\nimport { existsSync, readFileSync } from \"fs\";\nimport { dirname, isAbsolute, join, resolve } from \"path\";\n\nconst DEFAULT_STYLEGUIDE_PATHS = [\n \".uilint/styleguide.md\",\n \".uilint/styleguide.yaml\",\n \".uilint/styleguide.yml\",\n];\n\n/**\n * Find workspace root by walking up looking for pnpm-workspace.yaml, package.json, or .git\n */\nfunction findWorkspaceRoot(startDir: string): string {\n let dir = startDir;\n for (let i = 0; i < 20; i++) {\n if (\n existsSync(join(dir, \"pnpm-workspace.yaml\")) ||\n existsSync(join(dir, \".git\"))\n ) {\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return startDir;\n}\n\n/**\n * Find the nearest package root (directory containing package.json),\n * stopping at the workspace root.\n */\nfunction findNearestPackageRoot(\n startDir: string,\n workspaceRoot: string\n): string {\n let dir = startDir;\n for (let i = 0; i < 30; i++) {\n if (existsSync(join(dir, \"package.json\"))) return dir;\n if (dir === workspaceRoot) break;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return startDir;\n}\n\n/**\n * Find the styleguide file path\n */\nexport function findStyleguidePath(\n startDir: string,\n explicitPath?: string\n): string | null {\n // Explicit path takes precedence\n if (explicitPath) {\n if (isAbsolute(explicitPath)) {\n return existsSync(explicitPath) ? explicitPath : null;\n }\n\n // For relative explicit paths, try:\n // 1) relative to the file dir (back-compat)\n // 2) relative to the nearest package root (typical \"project root\")\n // 3) relative to workspace root (monorepo root)\n const workspaceRoot = findWorkspaceRoot(startDir);\n const packageRoot = findNearestPackageRoot(startDir, workspaceRoot);\n\n const candidates = [\n resolve(startDir, explicitPath),\n resolve(packageRoot, explicitPath),\n resolve(workspaceRoot, explicitPath),\n ];\n\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n\n return null;\n }\n\n // Check from start dir up to workspace root\n const workspaceRoot = findWorkspaceRoot(startDir);\n let dir = startDir;\n\n while (true) {\n for (const relativePath of DEFAULT_STYLEGUIDE_PATHS) {\n const fullPath = join(dir, relativePath);\n if (existsSync(fullPath)) {\n return fullPath;\n }\n }\n\n // Stop at workspace root\n if (dir === workspaceRoot) break;\n\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n return null;\n}\n\n/**\n * Load styleguide content from file\n */\nexport function loadStyleguide(\n startDir: string,\n explicitPath?: string\n): string | null {\n const path = findStyleguidePath(startDir, explicitPath);\n if (!path) return null;\n\n try {\n return readFileSync(path, \"utf-8\");\n } catch {\n return null;\n }\n}\n\n/**\n * Get styleguide path and content\n */\nexport function getStyleguide(\n startDir: string,\n explicitPath?: string\n): { path: string | null; content: string | null } {\n const path = findStyleguidePath(startDir, explicitPath);\n if (!path) return { path: null, content: null };\n\n try {\n const content = readFileSync(path, \"utf-8\");\n return { path, content };\n } catch {\n return { path, content: null };\n }\n}\n","/**\n * Rule Registry\n *\n * Central registry of all UILint ESLint rules with metadata for CLI tooling.\n * This allows the installer to auto-discover available rules and present them\n * to the user with descriptions.\n */\n\nexport interface RuleMetadata {\n /** Rule identifier (e.g., \"no-arbitrary-tailwind\") */\n id: string;\n /** Display name for CLI */\n name: string;\n /** Short description for CLI selection prompts */\n description: string;\n /** Default severity level */\n defaultSeverity: \"error\" | \"warn\" | \"off\";\n /** Default options for the rule */\n defaultOptions?: unknown[];\n /** Whether this rule requires a styleguide file */\n requiresStyleguide?: boolean;\n /** Category for grouping */\n category: \"static\" | \"semantic\";\n}\n\n/**\n * Registry of all available UILint ESLint rules\n *\n * When adding a new rule:\n * 1. Add the rule implementation to src/rules/\n * 2. Add an entry here with metadata\n * 3. Export the rule from src/index.ts\n * 4. The CLI installer will automatically discover and offer it\n */\nexport const ruleRegistry: RuleMetadata[] = [\n {\n id: \"no-arbitrary-tailwind\",\n name: \"No Arbitrary Tailwind\",\n description: \"Forbid arbitrary values like w-[123px], bg-[#fff]\",\n defaultSeverity: \"error\",\n category: \"static\",\n },\n {\n id: \"consistent-spacing\",\n name: \"Consistent Spacing\",\n description: \"Enforce spacing scale (no magic numbers in gap/padding)\",\n defaultSeverity: \"warn\",\n defaultOptions: [{ scale: [0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16] }],\n category: \"static\",\n },\n {\n id: \"consistent-dark-mode\",\n name: \"Consistent Dark Mode\",\n description:\n \"Ensure consistent dark: theming (error on mix, warn on missing)\",\n defaultSeverity: \"error\",\n defaultOptions: [{ warnOnMissingDarkMode: true }],\n category: \"static\",\n },\n {\n id: \"no-direct-store-import\",\n name: \"No Direct Store Import\",\n description: \"Forbid direct Zustand store imports (use context hooks)\",\n defaultSeverity: \"warn\",\n defaultOptions: [{ storePattern: \"use*Store\" }],\n category: \"static\",\n },\n {\n id: \"prefer-zustand-state-management\",\n name: \"Prefer Zustand State Management\",\n description:\n \"Detect excessive useState/useReducer/useContext; suggest Zustand\",\n defaultSeverity: \"warn\",\n defaultOptions: [\n {\n maxStateHooks: 3,\n countUseState: true,\n countUseReducer: true,\n countUseContext: true,\n },\n ],\n category: \"static\",\n },\n {\n id: \"no-mixed-component-libraries\",\n name: \"No Mixed Component Libraries\",\n description: \"Forbid mixing component libraries (e.g., shadcn + MUI)\",\n defaultSeverity: \"error\",\n defaultOptions: [{ libraries: [\"shadcn\", \"mui\"] }],\n category: \"static\",\n },\n {\n id: \"semantic\",\n name: \"Semantic Analysis\",\n description: \"LLM-powered semantic UI analysis using your styleguide\",\n defaultSeverity: \"warn\",\n defaultOptions: [\n { model: \"qwen3-coder:30b\", styleguidePath: \".uilint/styleguide.md\" },\n ],\n requiresStyleguide: true,\n category: \"semantic\",\n },\n];\n\n/**\n * Get rule metadata by ID\n */\nexport function getRuleMetadata(id: string): RuleMetadata | undefined {\n return ruleRegistry.find((rule) => rule.id === id);\n}\n\n/**\n * Get all rules in a category\n */\nexport function getRulesByCategory(\n category: \"static\" | \"semantic\"\n): RuleMetadata[] {\n return ruleRegistry.filter((rule) => rule.category === category);\n}\n","/**\n * UILint ESLint Plugin\n *\n * THIS FILE IS AUTO-GENERATED from src/rule-registry.ts.\n * Do not edit by hand. Run: pnpm -C packages/uilint-eslint generate:index\n */\n\nimport type { Linter } from \"eslint\";\nimport noArbitraryTailwind from \"./rules/no-arbitrary-tailwind.js\";\nimport consistentSpacing from \"./rules/consistent-spacing.js\";\nimport consistentDarkMode from \"./rules/consistent-dark-mode.js\";\nimport noDirectStoreImport from \"./rules/no-direct-store-import.js\";\nimport preferZustandStateManagement from \"./rules/prefer-zustand-state-management.js\";\nimport noMixedComponentLibraries from \"./rules/no-mixed-component-libraries.js\";\nimport semantic from \"./rules/semantic.js\";\n\n/**\n * All available rules\n */\nconst rules = {\n \"no-arbitrary-tailwind\": noArbitraryTailwind,\n \"consistent-spacing\": consistentSpacing,\n \"consistent-dark-mode\": consistentDarkMode,\n \"no-direct-store-import\": noDirectStoreImport,\n \"prefer-zustand-state-management\": preferZustandStateManagement,\n \"no-mixed-component-libraries\": noMixedComponentLibraries,\n \"semantic\": semantic,\n};\n\n// Package version (injected at build time or fallback)\nconst version = \"0.1.0\";\n\n/**\n * Plugin metadata\n */\nconst meta = {\n name: \"uilint\",\n version,\n};\n\n/**\n * The ESLint plugin object\n */\nconst plugin = {\n meta,\n rules,\n};\n\n/**\n * Shared language options for all configs\n */\nconst jsxLanguageOptions: Linter.Config[\"languageOptions\"] = {\n parserOptions: {\n ecmaFeatures: {\n jsx: true,\n },\n },\n};\n\n/**\n * Recommended config - static rules only\n *\n * Usage:\n * ```js\n * import uilint from 'uilint-eslint';\n * export default [uilint.configs.recommended];\n * ```\n */\nconst recommendedConfig: Linter.Config = {\n name: \"uilint/recommended\",\n plugins: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n uilint: plugin as any,\n },\n languageOptions: jsxLanguageOptions,\n rules: {\n \"uilint/no-arbitrary-tailwind\": \"error\",\n \"uilint/consistent-spacing\": [\"warn\", ...[\n {\n \"scale\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6,\n 8,\n 10,\n 12,\n 16\n ]\n }\n ]],\n \"uilint/consistent-dark-mode\": [\"error\", ...[\n {\n \"warnOnMissingDarkMode\": true\n }\n ]],\n \"uilint/no-direct-store-import\": [\"warn\", ...[\n {\n \"storePattern\": \"use*Store\"\n }\n ]],\n \"uilint/prefer-zustand-state-management\": [\"warn\", ...[\n {\n \"maxStateHooks\": 3,\n \"countUseState\": true,\n \"countUseReducer\": true,\n \"countUseContext\": true\n }\n ]],\n \"uilint/no-mixed-component-libraries\": [\"error\", ...[\n {\n \"libraries\": [\n \"shadcn\",\n \"mui\"\n ]\n }\n ]],\n },\n};\n\n/**\n * Strict config - static rules + semantic rules\n *\n * Usage:\n * ```js\n * import uilint from 'uilint-eslint';\n * export default [uilint.configs.strict];\n * ```\n */\nconst strictConfig: Linter.Config = {\n name: \"uilint/strict\",\n plugins: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n uilint: plugin as any,\n },\n languageOptions: jsxLanguageOptions,\n rules: {\n \"uilint/no-arbitrary-tailwind\": \"error\",\n \"uilint/consistent-spacing\": [\"warn\", ...[\n {\n \"scale\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6,\n 8,\n 10,\n 12,\n 16\n ]\n }\n ]],\n \"uilint/consistent-dark-mode\": [\"error\", ...[\n {\n \"warnOnMissingDarkMode\": true\n }\n ]],\n \"uilint/no-direct-store-import\": [\"warn\", ...[\n {\n \"storePattern\": \"use*Store\"\n }\n ]],\n \"uilint/prefer-zustand-state-management\": [\"warn\", ...[\n {\n \"maxStateHooks\": 3,\n \"countUseState\": true,\n \"countUseReducer\": true,\n \"countUseContext\": true\n }\n ]],\n \"uilint/no-mixed-component-libraries\": [\"error\", ...[\n {\n \"libraries\": [\n \"shadcn\",\n \"mui\"\n ]\n }\n ]],\n \"uilint/semantic\": [\"warn\", ...[\n {\n \"model\": \"qwen3-coder:30b\",\n \"styleguidePath\": \".uilint/styleguide.md\"\n }\n ]],\n },\n};\n\n/**\n * Pre-configured configs\n */\nconst configs: Record<string, Linter.Config> = {\n recommended: recommendedConfig,\n strict: strictConfig,\n};\n\n/**\n * UILint ESLint export interface\n */\nexport interface UILintESLint {\n meta: typeof meta;\n plugin: typeof plugin;\n rules: typeof rules;\n configs: Record<string, Linter.Config>;\n}\n\n/**\n * Default export for ESLint flat config\n */\nconst uilintEslint: UILintESLint = {\n meta,\n plugin,\n rules,\n configs,\n};\n\nexport default uilintEslint;\n\n// Named exports for convenience\nexport { plugin, rules, configs, meta };\n\n// Re-export utilities for custom rule creation\nexport { createRule } from \"./utils/create-rule.js\";\nexport {\n loadStyleguide,\n findStyleguidePath,\n getStyleguide,\n} from \"./utils/styleguide-loader.js\";\nexport {\n hashContent,\n hashContentSync,\n getCacheEntry,\n setCacheEntry,\n clearCache,\n clearCacheEntry,\n loadCache,\n saveCache,\n type CacheEntry,\n type CachedIssue,\n type CacheStore,\n} from \"./utils/cache.js\";\n\n// Re-export rule registry for CLI tooling\nexport {\n ruleRegistry,\n getRuleMetadata,\n getRulesByCategory,\n type RuleMetadata,\n} from \"./rule-registry.js\";\n"],"mappings":"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","names":["checkClassString","existsSync","readFileSync","dirname","join","existsSync","readFileSync","dirname","join","existsSync","readFileSync","dirname","join","workspaceRoot","dirname","readFileSync","findProjectRoot","existsSync","join"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/create-rule.ts","../src/rules/no-arbitrary-tailwind.ts","../src/rules/consistent-spacing.ts","../src/rules/consistent-dark-mode.ts","../src/rules/no-direct-store-import.ts","../src/rules/prefer-zustand-state-management.ts","../src/utils/export-resolver.ts","../src/utils/component-parser.ts","../src/utils/import-graph.ts","../src/rules/no-mixed-component-libraries.ts","../src/rules/semantic.ts","../src/utils/cache.ts","../src/utils/styleguide-loader.ts","../src/rule-registry.ts","../src/index.ts"],"sourcesContent":["/**\n * Rule creation helper using @typescript-eslint/utils\n */\n\nimport { ESLintUtils } from \"@typescript-eslint/utils\";\n\nexport const createRule = ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/peter-suggate/uilint/blob/main/packages/uilint-eslint/docs/rules/${name}.md`\n);\n","/**\n * Rule: no-arbitrary-tailwind\n *\n * Forbids arbitrary Tailwind values like w-[123px], bg-[#fff], etc.\n */\n\nimport { createRule } from \"../utils/create-rule.js\";\nimport type { TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"noArbitraryValue\";\ntype Options = [];\n\n// Regex to match arbitrary Tailwind values: word-[anything]\nconst ARBITRARY_VALUE_REGEX = /\\b[\\w-]+-\\[[^\\]]+\\]/g;\n\nexport default createRule<Options, MessageIds>({\n name: \"no-arbitrary-tailwind\",\n meta: {\n type: \"problem\",\n docs: {\n description: \"Forbid arbitrary Tailwind values like w-[123px]\",\n },\n messages: {\n noArbitraryValue:\n \"Avoid arbitrary Tailwind value '{{value}}'. Use the spacing/color scale instead.\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n return {\n // Check className attributes in JSX\n JSXAttribute(node) {\n if (\n node.name.type === \"JSXIdentifier\" &&\n (node.name.name === \"className\" || node.name.name === \"class\")\n ) {\n const value = node.value;\n\n // Handle string literal: className=\"...\"\n if (value?.type === \"Literal\" && typeof value.value === \"string\") {\n checkClassString(context, value, value.value);\n }\n\n // Handle JSX expression: className={...}\n if (value?.type === \"JSXExpressionContainer\") {\n const expr = value.expression;\n\n // Direct string: className={\"...\"}\n if (expr.type === \"Literal\" && typeof expr.value === \"string\") {\n checkClassString(context, expr, expr.value);\n }\n\n // Template literal: className={`...`}\n if (expr.type === \"TemplateLiteral\") {\n for (const quasi of expr.quasis) {\n checkClassString(context, quasi, quasi.value.raw);\n }\n }\n }\n }\n },\n\n // Check cn(), clsx(), classnames() calls\n CallExpression(node) {\n if (node.callee.type !== \"Identifier\") return;\n const name = node.callee.name;\n\n if (name === \"cn\" || name === \"clsx\" || name === \"classnames\") {\n for (const arg of node.arguments) {\n if (arg.type === \"Literal\" && typeof arg.value === \"string\") {\n checkClassString(context, arg, arg.value);\n }\n if (arg.type === \"TemplateLiteral\") {\n for (const quasi of arg.quasis) {\n checkClassString(context, quasi, quasi.value.raw);\n }\n }\n }\n }\n },\n };\n },\n});\n\nfunction checkClassString(\n context: Parameters<\n ReturnType<typeof createRule<[], \"noArbitraryValue\">>[\"create\"]\n >[0],\n node: TSESTree.Node,\n classString: string\n) {\n const matches = classString.matchAll(ARBITRARY_VALUE_REGEX);\n\n for (const match of matches) {\n // Ignore data attributes (e.g., data-[value], data-test-[something])\n if (match[0].startsWith(\"data-\")) {\n continue;\n }\n\n context.report({\n node,\n messageId: \"noArbitraryValue\",\n data: { value: match[0] },\n });\n }\n}\n","/**\n * Rule: consistent-spacing\n *\n * Enforces use of spacing scale values in gap, padding, margin utilities.\n */\n\nimport { createRule } from \"../utils/create-rule.js\";\nimport type { TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"invalidSpacing\";\ntype Options = [\n {\n scale?: number[];\n }\n];\n\n// Default Tailwind spacing scale\nconst DEFAULT_SCALE = [\n 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 24,\n 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 96,\n];\n\n// Spacing utilities that take numeric values\nconst SPACING_PREFIXES = [\n \"p-\",\n \"px-\",\n \"py-\",\n \"pt-\",\n \"pr-\",\n \"pb-\",\n \"pl-\",\n \"ps-\",\n \"pe-\",\n \"m-\",\n \"mx-\",\n \"my-\",\n \"mt-\",\n \"mr-\",\n \"mb-\",\n \"ml-\",\n \"ms-\",\n \"me-\",\n \"gap-\",\n \"gap-x-\",\n \"gap-y-\",\n \"space-x-\",\n \"space-y-\",\n \"inset-\",\n \"inset-x-\",\n \"inset-y-\",\n \"top-\",\n \"right-\",\n \"bottom-\",\n \"left-\",\n \"w-\",\n \"h-\",\n \"min-w-\",\n \"min-h-\",\n \"max-w-\",\n \"max-h-\",\n \"size-\",\n];\n\n// Build regex to match spacing utilities with numeric values\nfunction buildSpacingRegex(): RegExp {\n const prefixes = SPACING_PREFIXES.map((p) => p.replace(\"-\", \"\\\\-\")).join(\"|\");\n // Match prefix followed by a number (possibly with decimal)\n return new RegExp(`\\\\b(${prefixes})(\\\\d+\\\\.?\\\\d*)\\\\b`, \"g\");\n}\n\nconst SPACING_REGEX = buildSpacingRegex();\n\nexport default createRule<Options, MessageIds>({\n name: \"consistent-spacing\",\n meta: {\n type: \"suggestion\",\n docs: {\n description: \"Enforce spacing scale (no magic numbers in gap/padding)\",\n },\n messages: {\n invalidSpacing:\n \"Spacing value '{{value}}' is not in the allowed scale. Use one of: {{allowed}}\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n scale: {\n type: \"array\",\n items: { type: \"number\" },\n },\n },\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [{ scale: DEFAULT_SCALE }],\n create(context) {\n const options = context.options[0] || {};\n const scale = new Set((options.scale || DEFAULT_SCALE).map(String));\n const scaleList = [...scale].slice(0, 10).join(\", \") + \"...\";\n\n return {\n // Check className attributes in JSX\n JSXAttribute(node) {\n if (\n node.name.type === \"JSXIdentifier\" &&\n (node.name.name === \"className\" || node.name.name === \"class\")\n ) {\n const value = node.value;\n\n if (value?.type === \"Literal\" && typeof value.value === \"string\") {\n checkSpacing(context, node, value.value, scale, scaleList);\n }\n\n if (value?.type === \"JSXExpressionContainer\") {\n const expr = value.expression;\n if (expr.type === \"Literal\" && typeof expr.value === \"string\") {\n checkSpacing(context, node, expr.value, scale, scaleList);\n }\n if (expr.type === \"TemplateLiteral\") {\n for (const quasi of expr.quasis) {\n checkSpacing(context, node, quasi.value.raw, scale, scaleList);\n }\n }\n }\n }\n },\n\n // Check cn(), clsx(), classnames() calls\n CallExpression(node) {\n if (node.callee.type !== \"Identifier\") return;\n const name = node.callee.name;\n\n if (name === \"cn\" || name === \"clsx\" || name === \"classnames\") {\n for (const arg of node.arguments) {\n if (arg.type === \"Literal\" && typeof arg.value === \"string\") {\n checkSpacing(context, arg, arg.value, scale, scaleList);\n }\n if (arg.type === \"TemplateLiteral\") {\n for (const quasi of arg.quasis) {\n checkSpacing(context, quasi, quasi.value.raw, scale, scaleList);\n }\n }\n }\n }\n },\n };\n },\n});\n\nfunction checkSpacing(\n context: Parameters<\n ReturnType<typeof createRule<Options, \"invalidSpacing\">>[\"create\"]\n >[0],\n node: TSESTree.Node,\n classString: string,\n scale: Set<string>,\n scaleList: string\n) {\n // Reset regex state\n SPACING_REGEX.lastIndex = 0;\n\n let match;\n while ((match = SPACING_REGEX.exec(classString)) !== null) {\n const [, , value] = match;\n if (value && !scale.has(value)) {\n context.report({\n node,\n messageId: \"invalidSpacing\",\n data: { value, allowed: scaleList },\n });\n }\n }\n}\n","/**\n * Rule: consistent-dark-mode\n *\n * Ensures consistent dark mode theming in Tailwind CSS classes.\n * - Error: When some color classes have dark: variants but others don't within the same element\n * - Warning: When Tailwind color classes are used in a file but no dark: theming exists\n */\n\nimport { createRule } from \"../utils/create-rule.js\";\nimport type { TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"inconsistentDarkMode\" | \"missingDarkMode\";\ntype Options = [\n {\n /** Whether to warn when no dark mode classes are found in a file that uses Tailwind colors. Default: true */\n warnOnMissingDarkMode?: boolean;\n }?\n];\n\n// Color-related class prefixes that should have dark mode variants\nconst COLOR_PREFIXES = [\n \"bg-\",\n \"text-\",\n \"border-\",\n \"border-t-\",\n \"border-r-\",\n \"border-b-\",\n \"border-l-\",\n \"border-x-\",\n \"border-y-\",\n \"ring-\",\n \"ring-offset-\",\n \"divide-\",\n \"outline-\",\n \"shadow-\",\n \"accent-\",\n \"caret-\",\n \"fill-\",\n \"stroke-\",\n \"decoration-\",\n \"placeholder-\",\n \"from-\",\n \"via-\",\n \"to-\",\n];\n\n// Values that don't need dark variants (colorless or inherited)\nconst EXEMPT_SUFFIXES = [\"transparent\", \"inherit\", \"current\", \"auto\", \"none\"];\n\n// Known non-color utilities that use color prefixes\n// These are utilities like text-lg (font size), text-center (alignment), etc.\nconst NON_COLOR_UTILITIES = new Set([\n // Exempt values (colorless or inherited) - don't need dark variants\n \"transparent\",\n \"inherit\",\n \"current\",\n \"auto\",\n \"none\",\n // text- utilities that aren't colors\n \"xs\",\n \"sm\",\n \"base\",\n \"lg\",\n \"xl\",\n \"2xl\",\n \"3xl\",\n \"4xl\",\n \"5xl\",\n \"6xl\",\n \"7xl\",\n \"8xl\",\n \"9xl\",\n \"left\",\n \"center\",\n \"right\",\n \"justify\",\n \"start\",\n \"end\",\n \"wrap\",\n \"nowrap\",\n \"balance\",\n \"pretty\",\n \"ellipsis\",\n \"clip\",\n // border- utilities that aren't colors\n \"0\",\n \"2\",\n \"4\",\n \"8\",\n \"solid\",\n \"dashed\",\n \"dotted\",\n \"double\",\n \"hidden\",\n \"collapse\",\n \"separate\",\n // shadow- utilities that aren't colors\n // Note: \"sm\", \"lg\", \"xl\", \"2xl\" already included above\n \"md\",\n \"inner\",\n // ring- utilities that aren't colors\n // Note: \"0\", \"2\", \"4\", \"8\" already included above\n \"1\",\n \"inset\",\n // outline- utilities that aren't colors\n // Note: numeric values already included\n \"offset-0\",\n \"offset-1\",\n \"offset-2\",\n \"offset-4\",\n \"offset-8\",\n // decoration- utilities that aren't colors\n // Note: \"solid\", \"double\", \"dotted\", \"dashed\" already included\n \"wavy\",\n \"from-font\",\n \"clone\",\n \"slice\",\n // divide- utilities that aren't colors\n \"x\",\n \"y\",\n \"x-0\",\n \"x-2\",\n \"x-4\",\n \"x-8\",\n \"y-0\",\n \"y-2\",\n \"y-4\",\n \"y-8\",\n \"x-reverse\",\n \"y-reverse\",\n // gradient direction utilities (from-, via-, to- prefixes)\n \"t\",\n \"tr\",\n \"r\",\n \"br\",\n \"b\",\n \"bl\",\n \"l\",\n \"tl\",\n]);\n\n// Semantic color names used by theming systems like shadcn\n// These are CSS variable-based colors that handle dark mode automatically\nconst SEMANTIC_COLOR_NAMES = new Set([\n // Core shadcn colors\n \"background\",\n \"foreground\",\n // Component colors\n \"card\",\n \"card-foreground\",\n \"popover\",\n \"popover-foreground\",\n \"primary\",\n \"primary-foreground\",\n \"secondary\",\n \"secondary-foreground\",\n \"muted\",\n \"muted-foreground\",\n \"accent\",\n \"accent-foreground\",\n \"destructive\",\n \"destructive-foreground\",\n // Form/UI colors\n \"border\",\n \"input\",\n \"ring\",\n // Sidebar colors (shadcn sidebar component)\n \"sidebar\",\n \"sidebar-foreground\",\n \"sidebar-border\",\n \"sidebar-primary\",\n \"sidebar-primary-foreground\",\n \"sidebar-accent\",\n \"sidebar-accent-foreground\",\n \"sidebar-ring\",\n]);\n\n// Pattern for semantic chart colors (chart-1, chart-2, etc.)\nconst CHART_COLOR_PATTERN = /^chart-\\d+$/;\n\n/**\n * Check if a class has 'dark' in its variant chain\n */\nfunction hasDarkVariant(className: string): boolean {\n const parts = className.split(\":\");\n // All parts except the last are variants\n const variants = parts.slice(0, -1);\n return variants.includes(\"dark\");\n}\n\n/**\n * Get the base class (without any variants like hover:, dark:, md:, etc.)\n */\nfunction getBaseClass(className: string): string {\n const parts = className.split(\":\");\n return parts[parts.length - 1] || \"\";\n}\n\n/**\n * Find the color prefix this class uses, if any\n */\nfunction getColorPrefix(baseClass: string): string | null {\n // Sort by length descending to match more specific prefixes first\n // (e.g., \"border-t-\" before \"border-\")\n const sortedPrefixes = [...COLOR_PREFIXES].sort(\n (a, b) => b.length - a.length\n );\n return sortedPrefixes.find((p) => baseClass.startsWith(p)) || null;\n}\n\n/**\n * Check if the value is a semantic/themed color (e.g., shadcn)\n * These colors use CSS variables that automatically handle dark mode\n */\nfunction isSemanticColor(value: string): boolean {\n // Check for exact semantic color names\n if (SEMANTIC_COLOR_NAMES.has(value)) {\n return true;\n }\n\n // Check for chart colors (chart-1, chart-2, etc.)\n if (CHART_COLOR_PATTERN.test(value)) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Check if the value after the prefix looks like a color value\n * Uses an exclusion-based approach: anything that's not a known non-color utility\n * and not a semantic color is treated as a potential color.\n */\nfunction isColorValue(baseClass: string, prefix: string): boolean {\n const value = baseClass.slice(prefix.length);\n\n // Empty value is not a color\n if (!value) {\n return false;\n }\n\n // Check if it's a semantic/themed color (exempt from dark mode requirements)\n if (isSemanticColor(value)) {\n return false;\n }\n\n // Check if it's a known non-color utility\n if (NON_COLOR_UTILITIES.has(value)) {\n return false;\n }\n\n // Treat everything else as a potential color\n // This catches:\n // - Standard Tailwind colors: blue-500, slate-900, white, black\n // - Custom colors defined in tailwind.config: brand, primary (non-shadcn), custom-blue\n // - Arbitrary values: [#fff], [rgb(255,0,0)], [var(--my-color)]\n // - Opacity modifiers: blue-500/50, white/80\n return true;\n}\n\n/**\n * Check if a class is exempt from dark mode requirements\n */\nfunction isExempt(baseClass: string): boolean {\n return EXEMPT_SUFFIXES.some((suffix) => baseClass.endsWith(suffix));\n}\n\nexport default createRule<Options, MessageIds>({\n name: \"consistent-dark-mode\",\n meta: {\n type: \"problem\",\n docs: {\n description: \"Ensure consistent dark mode theming in Tailwind classes\",\n },\n messages: {\n inconsistentDarkMode:\n \"Inconsistent dark mode: '{{unthemed}}' lack dark: variants while other color classes have them.\",\n missingDarkMode:\n \"No dark mode theming detected. Consider adding dark: variants for color classes.\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n warnOnMissingDarkMode: {\n type: \"boolean\",\n description:\n \"Whether to warn when no dark mode classes are found in a file that uses Tailwind colors\",\n },\n },\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [{ warnOnMissingDarkMode: true }],\n create(context) {\n const options = context.options[0] || {};\n const warnOnMissingDarkMode = options.warnOnMissingDarkMode ?? true;\n\n let fileHasColorClasses = false;\n let fileHasDarkMode = false;\n const reportedNodes = new Set<TSESTree.Node>();\n\n function checkClassString(node: TSESTree.Node, classString: string) {\n const classes = classString.split(/\\s+/).filter(Boolean);\n if (classes.length === 0) return;\n\n // Track usage per color prefix: { hasLight, hasDark, lightClasses }\n const prefixUsage = new Map<\n string,\n { hasLight: boolean; hasDark: boolean; lightClasses: string[] }\n >();\n\n for (const cls of classes) {\n const baseClass = getBaseClass(cls);\n const prefix = getColorPrefix(baseClass);\n\n if (!prefix) continue;\n if (isExempt(baseClass)) continue;\n\n // Verify this is actually a color class, not something like text-lg\n if (!isColorValue(baseClass, prefix)) continue;\n\n if (!prefixUsage.has(prefix)) {\n prefixUsage.set(prefix, {\n hasLight: false,\n hasDark: false,\n lightClasses: [],\n });\n }\n\n const usage = prefixUsage.get(prefix)!;\n\n if (hasDarkVariant(cls)) {\n usage.hasDark = true;\n fileHasDarkMode = true;\n } else {\n usage.hasLight = true;\n usage.lightClasses.push(cls);\n }\n }\n\n // Track if file uses color classes\n if (prefixUsage.size > 0) {\n fileHasColorClasses = true;\n }\n\n // Check for inconsistency: some prefixes have dark variants, others don't\n const entries = Array.from(prefixUsage.entries());\n const hasSomeDark = entries.some(([_, u]) => u.hasDark);\n\n if (hasSomeDark) {\n const unthemedEntries = entries.filter(\n ([_, usage]) => usage.hasLight && !usage.hasDark\n );\n\n if (unthemedEntries.length > 0 && !reportedNodes.has(node)) {\n reportedNodes.add(node);\n // Collect the actual class names that lack dark variants\n const unthemedClasses = unthemedEntries.flatMap(\n ([_, u]) => u.lightClasses\n );\n\n context.report({\n node,\n messageId: \"inconsistentDarkMode\",\n data: { unthemed: unthemedClasses.join(\", \") },\n });\n }\n }\n }\n\n function processStringValue(node: TSESTree.Node, value: string) {\n checkClassString(node, value);\n }\n\n function processTemplateLiteral(node: TSESTree.TemplateLiteral) {\n for (const quasi of node.quasis) {\n checkClassString(quasi, quasi.value.raw);\n }\n }\n\n return {\n // Check className attributes in JSX\n JSXAttribute(node) {\n if (\n node.name.type === \"JSXIdentifier\" &&\n (node.name.name === \"className\" || node.name.name === \"class\")\n ) {\n const value = node.value;\n\n // Handle string literal: className=\"...\"\n if (value?.type === \"Literal\" && typeof value.value === \"string\") {\n processStringValue(value, value.value);\n }\n\n // Handle JSX expression: className={...}\n if (value?.type === \"JSXExpressionContainer\") {\n const expr = value.expression;\n\n // Direct string: className={\"...\"}\n if (expr.type === \"Literal\" && typeof expr.value === \"string\") {\n processStringValue(expr, expr.value);\n }\n\n // Template literal: className={`...`}\n if (expr.type === \"TemplateLiteral\") {\n processTemplateLiteral(expr);\n }\n }\n }\n },\n\n // Check cn(), clsx(), classnames(), cva() calls\n CallExpression(node) {\n if (node.callee.type !== \"Identifier\") return;\n const name = node.callee.name;\n\n if (\n name === \"cn\" ||\n name === \"clsx\" ||\n name === \"classnames\" ||\n name === \"cva\" ||\n name === \"twMerge\"\n ) {\n for (const arg of node.arguments) {\n if (arg.type === \"Literal\" && typeof arg.value === \"string\") {\n processStringValue(arg, arg.value);\n }\n if (arg.type === \"TemplateLiteral\") {\n processTemplateLiteral(arg);\n }\n // Handle arrays of class strings\n if (arg.type === \"ArrayExpression\") {\n for (const element of arg.elements) {\n if (\n element?.type === \"Literal\" &&\n typeof element.value === \"string\"\n ) {\n processStringValue(element, element.value);\n }\n if (element?.type === \"TemplateLiteral\") {\n processTemplateLiteral(element);\n }\n }\n }\n }\n }\n },\n\n // At the end of the file, check if Tailwind colors are used without any dark mode\n \"Program:exit\"(node) {\n if (warnOnMissingDarkMode && fileHasColorClasses && !fileHasDarkMode) {\n context.report({\n node,\n messageId: \"missingDarkMode\",\n });\n }\n },\n };\n },\n});\n","/**\n * Rule: no-direct-store-import\n *\n * Forbids direct Zustand store imports - prefer using hooks via context.\n */\n\nimport { createRule } from \"../utils/create-rule.js\";\n\ntype MessageIds = \"noDirectImport\";\ntype Options = [\n {\n storePattern?: string;\n }\n];\n\n// Convert glob pattern to regex\nfunction patternToRegex(pattern: string): RegExp {\n const escaped = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*/g, \".*\")\n .replace(/\\?/g, \".\");\n return new RegExp(`^${escaped}$`);\n}\n\nexport default createRule<Options, MessageIds>({\n name: \"no-direct-store-import\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Forbid direct Zustand store imports (use hooks via context)\",\n },\n messages: {\n noDirectImport:\n \"Avoid importing store '{{name}}' directly. Use the store via a context hook instead.\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n storePattern: {\n type: \"string\",\n description: \"Glob pattern for store names\",\n },\n },\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [{ storePattern: \"use*Store\" }],\n create(context) {\n const options = context.options[0] || {};\n const pattern = options.storePattern || \"use*Store\";\n const regex = patternToRegex(pattern);\n\n return {\n ImportDeclaration(node) {\n // Check if importing from a store file\n const source = node.source.value as string;\n if (!source.includes(\"store\")) return;\n\n // Check imported specifiers\n for (const specifier of node.specifiers) {\n if (specifier.type === \"ImportSpecifier\") {\n const importedName =\n specifier.imported.type === \"Identifier\"\n ? specifier.imported.name\n : specifier.imported.value;\n\n if (regex.test(importedName)) {\n context.report({\n node: specifier,\n messageId: \"noDirectImport\",\n data: { name: importedName },\n });\n }\n }\n\n if (specifier.type === \"ImportDefaultSpecifier\") {\n const localName = specifier.local.name;\n if (regex.test(localName)) {\n context.report({\n node: specifier,\n messageId: \"noDirectImport\",\n data: { name: localName },\n });\n }\n }\n }\n },\n };\n },\n});\n","/**\n * Rule: prefer-zustand-state-management\n *\n * Detects excessive use of React state hooks (useState, useReducer, useContext)\n * in components and suggests using Zustand stores for better state management.\n */\n\nimport { createRule } from \"../utils/create-rule.js\";\nimport type { TSESTree } from \"@typescript-eslint/utils\";\n\ntype MessageIds = \"excessiveStateHooks\";\ntype Options = [\n {\n /** Maximum number of state hooks before warning. Default: 3 */\n maxStateHooks?: number;\n /** Whether to count useState calls. Default: true */\n countUseState?: boolean;\n /** Whether to count useReducer calls. Default: true */\n countUseReducer?: boolean;\n /** Whether to count useContext calls. Default: true */\n countUseContext?: boolean;\n }?\n];\n\ninterface ComponentInfo {\n name: string;\n node: TSESTree.Node;\n hookCount: number;\n functionNode:\n | TSESTree.FunctionDeclaration\n | TSESTree.FunctionExpression\n | TSESTree.ArrowFunctionExpression;\n}\n\nconst STATE_HOOKS = new Set([\"useState\", \"useReducer\", \"useContext\"]);\n\nexport default createRule<Options, MessageIds>({\n name: \"prefer-zustand-state-management\",\n meta: {\n type: \"suggestion\",\n docs: {\n description:\n \"Detect excessive use of React state hooks and suggest Zustand stores\",\n },\n messages: {\n excessiveStateHooks:\n \"Component '{{component}}' has {{count}} state hooks (max: {{max}}). Consider using a Zustand store for state management.\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n maxStateHooks: {\n type: \"number\",\n minimum: 1,\n description: \"Maximum number of state hooks before warning\",\n },\n countUseState: {\n type: \"boolean\",\n description: \"Whether to count useState calls\",\n },\n countUseReducer: {\n type: \"boolean\",\n description: \"Whether to count useReducer calls\",\n },\n countUseContext: {\n type: \"boolean\",\n description: \"Whether to count useContext calls\",\n },\n },\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [\n {\n maxStateHooks: 3,\n countUseState: true,\n countUseReducer: true,\n countUseContext: true,\n },\n ],\n create(context) {\n const options = context.options[0] || {};\n const maxStateHooks = options.maxStateHooks ?? 3;\n const countUseState = options.countUseState ?? true;\n const countUseReducer = options.countUseReducer ?? true;\n const countUseContext = options.countUseContext ?? true;\n\n // Stack to track current component context\n const componentStack: ComponentInfo[] = [];\n\n // Set of function nodes we've identified as components to check\n const componentFunctions = new Map<TSESTree.Node, ComponentInfo>();\n\n /**\n * Check if a function name indicates a React component (PascalCase)\n */\n function isComponentName(name: string | null | undefined): boolean {\n if (!name) return false;\n // Components start with uppercase, hooks start with lowercase \"use\"\n return /^[A-Z]/.test(name);\n }\n\n /**\n * Check if a function name indicates a custom hook (starts with \"use\")\n */\n function isCustomHookName(name: string | null | undefined): boolean {\n if (!name) return false;\n return /^use[A-Z]/.test(name);\n }\n\n /**\n * Get the name of a function from various declaration patterns\n */\n function getFunctionName(\n node:\n | TSESTree.FunctionDeclaration\n | TSESTree.FunctionExpression\n | TSESTree.ArrowFunctionExpression\n ): string | null {\n // Function declaration: function MyComponent() {}\n if (node.type === \"FunctionDeclaration\" && node.id) {\n return node.id.name;\n }\n\n // Check parent for variable declaration: const MyComponent = () => {}\n const parent = node.parent;\n\n if (\n parent?.type === \"VariableDeclarator\" &&\n parent.id.type === \"Identifier\"\n ) {\n return parent.id.name;\n }\n\n // Check for forwardRef/memo: const MyComponent = forwardRef(function MyComponent() {})\n // or const MyComponent = forwardRef(() => {})\n if (parent?.type === \"CallExpression\") {\n const callParent = parent.parent;\n if (\n callParent?.type === \"VariableDeclarator\" &&\n callParent.id.type === \"Identifier\"\n ) {\n return callParent.id.name;\n }\n }\n\n // Named function expression: const x = function MyComponent() {}\n if (node.type === \"FunctionExpression\" && node.id) {\n return node.id.name;\n }\n\n return null;\n }\n\n /**\n * Check if a hook call should be counted based on options\n */\n function shouldCountHook(hookName: string): boolean {\n switch (hookName) {\n case \"useState\":\n return countUseState;\n case \"useReducer\":\n return countUseReducer;\n case \"useContext\":\n return countUseContext;\n default:\n return false;\n }\n }\n\n /**\n * Get hook name from a call expression (handles both useState and React.useState)\n */\n function getHookName(callee: TSESTree.Expression): string | null {\n // Direct call: useState()\n if (callee.type === \"Identifier\" && STATE_HOOKS.has(callee.name)) {\n return callee.name;\n }\n\n // Member expression: React.useState()\n if (\n callee.type === \"MemberExpression\" &&\n callee.object.type === \"Identifier\" &&\n callee.object.name === \"React\" &&\n callee.property.type === \"Identifier\" &&\n STATE_HOOKS.has(callee.property.name)\n ) {\n return callee.property.name;\n }\n\n return null;\n }\n\n /**\n * Check if we're directly inside a component function (not in a nested function)\n */\n function isDirectChildOfComponent(\n node: TSESTree.Node,\n componentNode: TSESTree.Node\n ): boolean {\n let current: TSESTree.Node | undefined = node.parent;\n\n while (current) {\n // If we hit the component node, we're a direct child\n if (current === componentNode) {\n return true;\n }\n\n // If we hit another function first, we're nested\n if (\n current.type === \"FunctionDeclaration\" ||\n current.type === \"FunctionExpression\" ||\n current.type === \"ArrowFunctionExpression\"\n ) {\n return false;\n }\n\n current = current.parent;\n }\n\n return false;\n }\n\n /**\n * Enter a function that might be a component\n */\n function enterFunction(\n node:\n | TSESTree.FunctionDeclaration\n | TSESTree.FunctionExpression\n | TSESTree.ArrowFunctionExpression\n ) {\n const name = getFunctionName(node);\n\n // Skip custom hooks - they're allowed to have many state hooks\n if (isCustomHookName(name)) {\n return;\n }\n\n // Skip non-component functions (lowercase names that aren't anonymous)\n if (name && !isComponentName(name)) {\n return;\n }\n\n // Track this as a potential component\n const componentInfo: ComponentInfo = {\n name: name || \"AnonymousComponent\",\n node,\n hookCount: 0,\n functionNode: node,\n };\n\n componentStack.push(componentInfo);\n componentFunctions.set(node, componentInfo);\n }\n\n /**\n * Exit a function and report if it had too many hooks\n */\n function exitFunction(\n node:\n | TSESTree.FunctionDeclaration\n | TSESTree.FunctionExpression\n | TSESTree.ArrowFunctionExpression\n ) {\n const componentInfo = componentFunctions.get(node);\n\n if (!componentInfo) {\n return;\n }\n\n // Remove from stack\n const index = componentStack.findIndex((c) => c.functionNode === node);\n if (index !== -1) {\n componentStack.splice(index, 1);\n }\n\n // Check if exceeded threshold\n if (componentInfo.hookCount > maxStateHooks) {\n context.report({\n node: componentInfo.node,\n messageId: \"excessiveStateHooks\",\n data: {\n component: componentInfo.name,\n count: componentInfo.hookCount,\n max: maxStateHooks,\n },\n });\n }\n\n componentFunctions.delete(node);\n }\n\n return {\n FunctionDeclaration: enterFunction,\n FunctionExpression: enterFunction,\n ArrowFunctionExpression: enterFunction,\n \"FunctionDeclaration:exit\": exitFunction,\n \"FunctionExpression:exit\": exitFunction,\n \"ArrowFunctionExpression:exit\": exitFunction,\n\n CallExpression(node) {\n const hookName = getHookName(node.callee);\n\n if (!hookName || !shouldCountHook(hookName)) {\n return;\n }\n\n // Find the innermost component this hook belongs to\n // We iterate from the end to find the most recent (innermost) component\n for (let i = componentStack.length - 1; i >= 0; i--) {\n const component = componentStack[i];\n\n if (isDirectChildOfComponent(node, component.functionNode)) {\n component.hookCount++;\n break;\n }\n }\n },\n };\n },\n});\n","/**\n * Export Resolver\n *\n * Resolves import paths and finds export definitions, following re-exports\n * to their original source files.\n */\n\nimport { ResolverFactory } from \"oxc-resolver\";\nimport { parse } from \"@typescript-eslint/typescript-estree\";\nimport { readFileSync, existsSync } from \"fs\";\nimport { dirname, join, extname } from \"path\";\nimport type { TSESTree } from \"@typescript-eslint/utils\";\n\n// Module-level resolver instance (reused across calls)\nlet resolverInstance: ReturnType<typeof ResolverFactory.prototype.sync> | null =\n null;\nlet resolverFactory: ResolverFactory | null = null;\n\n/**\n * Information about a resolved export\n */\nexport interface ResolvedExport {\n /** The name of the export (e.g., \"Button\") */\n name: string;\n /** Absolute path to the file containing the actual definition */\n filePath: string;\n /** The local name in the source file (may differ from export name) */\n localName: string;\n /** Whether this is a re-export (export { X } from './other') */\n isReexport: boolean;\n}\n\n/**\n * Cache for file exports to avoid re-parsing\n */\nconst exportCache = new Map<\n string,\n Map<string, { localName: string; reexportSource?: string }>\n>();\n\n/**\n * Cache for parsed ASTs\n */\nconst astCache = new Map<string, TSESTree.Program>();\n\n/**\n * Cache for resolved paths\n */\nconst resolvedPathCache = new Map<string, string | null>();\n\n/**\n * Get or create the resolver factory\n */\nfunction getResolverFactory(): ResolverFactory {\n if (!resolverFactory) {\n resolverFactory = new ResolverFactory({\n extensions: [\".tsx\", \".ts\", \".jsx\", \".js\"],\n mainFields: [\"module\", \"main\"],\n conditionNames: [\"import\", \"require\", \"node\", \"default\"],\n // Enable TypeScript path resolution\n tsconfig: {\n configFile: \"tsconfig.json\",\n references: \"auto\",\n },\n });\n }\n return resolverFactory;\n}\n\n/**\n * Resolve an import path to an absolute file path\n */\nexport function resolveImportPath(\n importSource: string,\n fromFile: string\n): string | null {\n const cacheKey = `${fromFile}::${importSource}`;\n\n if (resolvedPathCache.has(cacheKey)) {\n return resolvedPathCache.get(cacheKey) ?? null;\n }\n\n // Skip node_modules\n if (\n importSource.startsWith(\"react\") ||\n importSource.startsWith(\"next\") ||\n (!importSource.startsWith(\".\") &&\n !importSource.startsWith(\"@/\") &&\n !importSource.startsWith(\"~/\"))\n ) {\n // Check if it's a known external package\n if (\n importSource.includes(\"@mui/\") ||\n importSource.includes(\"@chakra-ui/\") ||\n importSource.includes(\"antd\") ||\n importSource.includes(\"@radix-ui/\")\n ) {\n // Return a marker for external packages - we don't resolve them but track them\n resolvedPathCache.set(cacheKey, null);\n return null;\n }\n resolvedPathCache.set(cacheKey, null);\n return null;\n }\n\n try {\n const factory = getResolverFactory();\n const fromDir = dirname(fromFile);\n const result = factory.sync(fromDir, importSource);\n\n if (result.path) {\n resolvedPathCache.set(cacheKey, result.path);\n return result.path;\n }\n } catch {\n // Fallback: try manual resolution for common patterns\n const resolved = manualResolve(importSource, fromFile);\n resolvedPathCache.set(cacheKey, resolved);\n return resolved;\n }\n\n resolvedPathCache.set(cacheKey, null);\n return null;\n}\n\n/**\n * Manual fallback resolution for common patterns\n */\nfunction manualResolve(importSource: string, fromFile: string): string | null {\n const fromDir = dirname(fromFile);\n const extensions = [\".tsx\", \".ts\", \".jsx\", \".js\"];\n\n // Handle @/ alias - find tsconfig and resolve\n if (importSource.startsWith(\"@/\")) {\n const projectRoot = findProjectRoot(fromFile);\n if (projectRoot) {\n const relativePath = importSource.slice(2); // Remove @/\n for (const ext of extensions) {\n const candidate = join(projectRoot, relativePath + ext);\n if (existsSync(candidate)) {\n return candidate;\n }\n // Try index file\n const indexCandidate = join(projectRoot, relativePath, `index${ext}`);\n if (existsSync(indexCandidate)) {\n return indexCandidate;\n }\n }\n }\n }\n\n // Handle relative imports\n if (importSource.startsWith(\".\")) {\n for (const ext of extensions) {\n const candidate = join(fromDir, importSource + ext);\n if (existsSync(candidate)) {\n return candidate;\n }\n // Try index file\n const indexCandidate = join(fromDir, importSource, `index${ext}`);\n if (existsSync(indexCandidate)) {\n return indexCandidate;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Find the project root by looking for tsconfig.json or package.json\n */\nfunction findProjectRoot(fromFile: string): string | null {\n let dir = dirname(fromFile);\n const root = \"/\";\n\n while (dir !== root) {\n if (existsSync(join(dir, \"tsconfig.json\"))) {\n return dir;\n }\n if (existsSync(join(dir, \"package.json\"))) {\n return dir;\n }\n dir = dirname(dir);\n }\n\n return null;\n}\n\n/**\n * Parse a file and cache the AST\n */\nexport function parseFile(filePath: string): TSESTree.Program | null {\n if (astCache.has(filePath)) {\n return astCache.get(filePath)!;\n }\n\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const ast = parse(content, {\n jsx: true,\n loc: true,\n range: true,\n });\n astCache.set(filePath, ast);\n return ast;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract export information from a file\n */\nfunction extractExports(\n filePath: string\n): Map<string, { localName: string; reexportSource?: string }> {\n if (exportCache.has(filePath)) {\n return exportCache.get(filePath)!;\n }\n\n const exports = new Map<\n string,\n { localName: string; reexportSource?: string }\n >();\n const ast = parseFile(filePath);\n\n if (!ast) {\n exportCache.set(filePath, exports);\n return exports;\n }\n\n for (const node of ast.body) {\n // Handle: export function Button() {}\n if (\n node.type === \"ExportNamedDeclaration\" &&\n node.declaration?.type === \"FunctionDeclaration\" &&\n node.declaration.id\n ) {\n exports.set(node.declaration.id.name, {\n localName: node.declaration.id.name,\n });\n }\n\n // Handle: export const Button = () => {}\n if (\n node.type === \"ExportNamedDeclaration\" &&\n node.declaration?.type === \"VariableDeclaration\"\n ) {\n for (const decl of node.declaration.declarations) {\n if (decl.id.type === \"Identifier\") {\n exports.set(decl.id.name, { localName: decl.id.name });\n }\n }\n }\n\n // Handle: export { Button } or export { Button as Btn }\n if (node.type === \"ExportNamedDeclaration\" && node.specifiers.length > 0) {\n const source = node.source?.value as string | undefined;\n for (const spec of node.specifiers) {\n if (spec.type === \"ExportSpecifier\") {\n const exportedName =\n spec.exported.type === \"Identifier\"\n ? spec.exported.name\n : spec.exported.value;\n const localName =\n spec.local.type === \"Identifier\"\n ? spec.local.name\n : spec.local.value;\n\n exports.set(exportedName, {\n localName,\n reexportSource: source,\n });\n }\n }\n }\n\n // Handle: export default function Button() {}\n if (\n node.type === \"ExportDefaultDeclaration\" &&\n node.declaration.type === \"FunctionDeclaration\" &&\n node.declaration.id\n ) {\n exports.set(\"default\", { localName: node.declaration.id.name });\n }\n\n // Handle: export default Button\n if (\n node.type === \"ExportDefaultDeclaration\" &&\n node.declaration.type === \"Identifier\"\n ) {\n exports.set(\"default\", { localName: node.declaration.name });\n }\n }\n\n exportCache.set(filePath, exports);\n return exports;\n}\n\n/**\n * Resolve an export to its original definition, following re-exports\n */\nexport function resolveExport(\n exportName: string,\n filePath: string,\n visited = new Set<string>()\n): ResolvedExport | null {\n // Cycle detection\n const key = `${filePath}::${exportName}`;\n if (visited.has(key)) {\n return null;\n }\n visited.add(key);\n\n const exports = extractExports(filePath);\n const exportInfo = exports.get(exportName);\n\n if (!exportInfo) {\n return null;\n }\n\n // If it's a re-export, follow the chain\n if (exportInfo.reexportSource) {\n const resolvedPath = resolveImportPath(exportInfo.reexportSource, filePath);\n if (resolvedPath) {\n return resolveExport(exportInfo.localName, resolvedPath, visited);\n }\n return null;\n }\n\n // This is the actual definition\n return {\n name: exportName,\n filePath,\n localName: exportInfo.localName,\n isReexport: false,\n };\n}\n\n/**\n * Clear all caches (useful for testing or watch mode)\n */\nexport function clearResolverCaches(): void {\n exportCache.clear();\n astCache.clear();\n resolvedPathCache.clear();\n}\n","/**\n * Component Parser\n *\n * Parses a single component's body to extract styling information\n * and identify nested component usage.\n */\n\nimport type { TSESTree } from \"@typescript-eslint/utils\";\nimport { parseFile } from \"./export-resolver.js\";\n\n/**\n * Known UI library import patterns\n */\nexport type LibraryName = \"shadcn\" | \"mui\" | \"chakra\" | \"antd\";\n\nexport const LIBRARY_PATTERNS: Record<LibraryName, string[]> = {\n shadcn: [\"@/components/ui\", \"@radix-ui/\", \"components/ui/\"],\n mui: [\"@mui/material\", \"@mui/icons-material\", \"@emotion/\"],\n chakra: [\"@chakra-ui/\"],\n antd: [\"antd\", \"@ant-design/\"],\n};\n\n/**\n * Information about a component used within another component\n */\nexport interface UsedComponent {\n /** Component name (e.g., \"Button\", \"Card\") */\n name: string;\n /** Import source path (e.g., \"@mui/material\", \"./button\") */\n importSource: string;\n /** Line number where the component is used */\n line: number;\n /** Column number where the component is used */\n column: number;\n}\n\n/**\n * Styling information extracted from a component\n */\nexport interface ComponentStyleInfo {\n /** Tailwind classes used in the component */\n tailwindClasses: string[];\n /** Inline style objects (as string representations) */\n inlineStyles: string[];\n /** Other components used within this component */\n usedComponents: UsedComponent[];\n /** Directly detected library (from import source) */\n directLibrary: LibraryName | null;\n}\n\n/**\n * Import map for a file: localName -> importSource\n */\nexport type ImportMap = Map<string, string>;\n\n/**\n * Extract imports from a file's AST\n */\nexport function extractImports(ast: TSESTree.Program): ImportMap {\n const imports = new Map<string, string>();\n\n for (const node of ast.body) {\n if (node.type === \"ImportDeclaration\") {\n const source = node.source.value as string;\n for (const spec of node.specifiers) {\n if (spec.type === \"ImportSpecifier\") {\n imports.set(spec.local.name, source);\n } else if (spec.type === \"ImportDefaultSpecifier\") {\n imports.set(spec.local.name, source);\n } else if (spec.type === \"ImportNamespaceSpecifier\") {\n imports.set(spec.local.name, source);\n }\n }\n }\n }\n\n return imports;\n}\n\n/**\n * Detect which UI library an import source belongs to\n */\nexport function detectLibraryFromSource(\n importSource: string\n): LibraryName | null {\n for (const [library, patterns] of Object.entries(LIBRARY_PATTERNS)) {\n if (patterns.some((p) => importSource.includes(p))) {\n return library as LibraryName;\n }\n }\n return null;\n}\n\n/**\n * Find a function/arrow function component definition by name in an AST\n */\nexport function findComponentDefinition(\n ast: TSESTree.Program,\n componentName: string\n): TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression | null {\n for (const node of ast.body) {\n // export function ComponentName() {}\n if (\n node.type === \"ExportNamedDeclaration\" &&\n node.declaration?.type === \"FunctionDeclaration\" &&\n node.declaration.id?.name === componentName\n ) {\n return node.declaration;\n }\n\n // export const ComponentName = () => {}\n if (\n node.type === \"ExportNamedDeclaration\" &&\n node.declaration?.type === \"VariableDeclaration\"\n ) {\n for (const decl of node.declaration.declarations) {\n if (\n decl.id.type === \"Identifier\" &&\n decl.id.name === componentName &&\n decl.init?.type === \"ArrowFunctionExpression\"\n ) {\n return decl.init;\n }\n }\n }\n\n // function ComponentName() {} (not exported directly)\n if (\n node.type === \"FunctionDeclaration\" &&\n node.id?.name === componentName\n ) {\n return node;\n }\n\n // const ComponentName = () => {}\n if (node.type === \"VariableDeclaration\") {\n for (const decl of node.declarations) {\n if (\n decl.id.type === \"Identifier\" &&\n decl.id.name === componentName &&\n decl.init?.type === \"ArrowFunctionExpression\"\n ) {\n return decl.init;\n }\n }\n }\n\n // export default function ComponentName() {}\n if (\n node.type === \"ExportDefaultDeclaration\" &&\n node.declaration.type === \"FunctionDeclaration\" &&\n node.declaration.id?.name === componentName\n ) {\n return node.declaration;\n }\n }\n\n return null;\n}\n\n/**\n * Extract Tailwind classes from a className string\n */\nfunction extractTailwindClasses(classString: string): string[] {\n return classString.split(/\\s+/).filter(Boolean);\n}\n\n/**\n * Recursively traverse a node and extract styling info\n */\nfunction traverseForStyling(\n node: TSESTree.Node,\n imports: ImportMap,\n result: ComponentStyleInfo\n): void {\n if (!node || typeof node !== \"object\") return;\n\n // Handle JSX elements\n if (node.type === \"JSXElement\" && node.openingElement) {\n const opening = node.openingElement;\n\n // Check if this is a component (PascalCase) or HTML element\n if (\n opening.name.type === \"JSXIdentifier\" &&\n /^[A-Z]/.test(opening.name.name)\n ) {\n const componentName = opening.name.name;\n const importSource = imports.get(componentName);\n\n if (importSource) {\n result.usedComponents.push({\n name: componentName,\n importSource,\n line: opening.loc.start.line,\n column: opening.loc.start.column,\n });\n\n // Check if this import is from a known UI library\n const library = detectLibraryFromSource(importSource);\n if (library && !result.directLibrary) {\n result.directLibrary = library;\n }\n }\n }\n\n // Handle JSX member expressions like Modal.Header\n if (opening.name.type === \"JSXMemberExpression\") {\n let objectName: string | null = null;\n let current = opening.name.object;\n while (current.type === \"JSXMemberExpression\") {\n current = current.object;\n }\n if (current.type === \"JSXIdentifier\") {\n objectName = current.name;\n }\n\n if (objectName) {\n const importSource = imports.get(objectName);\n if (importSource) {\n const library = detectLibraryFromSource(importSource);\n if (library && !result.directLibrary) {\n result.directLibrary = library;\n }\n }\n }\n }\n\n // Extract className/class attributes\n for (const attr of opening.attributes) {\n if (\n attr.type === \"JSXAttribute\" &&\n attr.name.type === \"JSXIdentifier\" &&\n (attr.name.name === \"className\" || attr.name.name === \"class\")\n ) {\n if (\n attr.value?.type === \"Literal\" &&\n typeof attr.value.value === \"string\"\n ) {\n result.tailwindClasses.push(\n ...extractTailwindClasses(attr.value.value)\n );\n }\n if (attr.value?.type === \"JSXExpressionContainer\") {\n const expr = attr.value.expression;\n if (expr.type === \"Literal\" && typeof expr.value === \"string\") {\n result.tailwindClasses.push(...extractTailwindClasses(expr.value));\n }\n if (expr.type === \"TemplateLiteral\") {\n for (const quasi of expr.quasis) {\n result.tailwindClasses.push(\n ...extractTailwindClasses(quasi.value.raw)\n );\n }\n }\n }\n }\n\n // Extract inline styles\n if (\n attr.type === \"JSXAttribute\" &&\n attr.name.type === \"JSXIdentifier\" &&\n attr.name.name === \"style\"\n ) {\n if (attr.value?.type === \"JSXExpressionContainer\") {\n // Just note that there's an inline style - we don't parse the object\n result.inlineStyles.push(\"[inline style]\");\n }\n }\n }\n }\n\n // Handle cn(), clsx(), twMerge() calls\n if (\n node.type === \"CallExpression\" &&\n node.callee.type === \"Identifier\" &&\n [\"cn\", \"clsx\", \"classnames\", \"twMerge\"].includes(node.callee.name)\n ) {\n for (const arg of node.arguments) {\n if (arg.type === \"Literal\" && typeof arg.value === \"string\") {\n result.tailwindClasses.push(...extractTailwindClasses(arg.value));\n }\n if (arg.type === \"TemplateLiteral\") {\n for (const quasi of arg.quasis) {\n result.tailwindClasses.push(\n ...extractTailwindClasses(quasi.value.raw)\n );\n }\n }\n }\n }\n\n // Recursively traverse all properties\n for (const key of Object.keys(node)) {\n if (key === \"parent\" || key === \"loc\" || key === \"range\") continue;\n\n const child = (node as unknown as Record<string, unknown>)[key];\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === \"object\") {\n traverseForStyling(item as TSESTree.Node, imports, result);\n }\n }\n } else if (child && typeof child === \"object\") {\n traverseForStyling(child as TSESTree.Node, imports, result);\n }\n }\n}\n\n/**\n * Parse a component's body and extract styling information\n */\nexport function parseComponentBody(\n filePath: string,\n componentName: string\n): ComponentStyleInfo | null {\n const ast = parseFile(filePath);\n if (!ast) return null;\n\n const imports = extractImports(ast);\n const componentDef = findComponentDefinition(ast, componentName);\n\n if (!componentDef) {\n return null;\n }\n\n const result: ComponentStyleInfo = {\n tailwindClasses: [],\n inlineStyles: [],\n usedComponents: [],\n directLibrary: null,\n };\n\n // Traverse the component body\n if (componentDef.body) {\n traverseForStyling(componentDef.body, imports, result);\n }\n\n // Deduplicate classes\n result.tailwindClasses = [...new Set(result.tailwindClasses)];\n\n return result;\n}\n\n/**\n * Analyze a file and extract all component usages with their libraries\n * (used for the entry file analysis)\n */\nexport function analyzeFileImports(\n filePath: string\n): Map<string, { importSource: string; library: LibraryName | null }> {\n const ast = parseFile(filePath);\n if (!ast) return new Map();\n\n const result = new Map<\n string,\n { importSource: string; library: LibraryName | null }\n >();\n const imports = extractImports(ast);\n\n for (const [name, source] of imports) {\n result.set(name, {\n importSource: source,\n library: detectLibraryFromSource(source),\n });\n }\n\n return result;\n}\n","/**\n * Import Graph Service\n *\n * Provides demand-driven cross-file analysis to detect UI library usage\n * across component trees. Uses in-memory caching for performance.\n */\n\nimport {\n resolveImportPath,\n resolveExport,\n clearResolverCaches,\n} from \"./export-resolver.js\";\nimport {\n parseComponentBody,\n detectLibraryFromSource,\n type LibraryName,\n type ComponentStyleInfo,\n} from \"./component-parser.js\";\n\n/**\n * Information about a component's UI library usage\n */\nexport interface ComponentLibraryInfo {\n /** Direct library (from import source, e.g., \"@mui/material\" -> \"mui\") */\n library: LibraryName | null;\n /** Libraries used internally by this component (for local components) */\n internalLibraries: Set<LibraryName>;\n /** Evidence of which internal components caused the library detection */\n libraryEvidence: Array<{\n componentName: string;\n library: LibraryName;\n }>;\n /** Whether this is a local component (resolved from project files) */\n isLocalComponent: boolean;\n}\n\n/**\n * Cache for analyzed components: \"filePath::componentName\" -> ComponentLibraryInfo\n */\nconst componentLibraryCache = new Map<string, ComponentLibraryInfo>();\n\n/**\n * Get a singleton instance of the import graph service\n */\nexport function getImportGraphService() {\n return {\n getComponentLibrary,\n clearCache,\n };\n}\n\n/**\n * Analyze a component's library usage, including transitive dependencies\n *\n * @param contextFilePath - The file where the component is used (for resolving relative imports)\n * @param componentName - The name of the component (e.g., \"Button\", \"MyCard\")\n * @param importSource - The import source (e.g., \"@mui/material\", \"./components/cards\")\n * @returns Library information including direct and transitive library usage\n */\nexport function getComponentLibrary(\n contextFilePath: string,\n componentName: string,\n importSource: string\n): ComponentLibraryInfo {\n // Check if import source directly indicates a known library\n const directLibrary = detectLibraryFromSource(importSource);\n\n if (directLibrary) {\n // It's a direct import from a known library (e.g., @mui/material)\n return {\n library: directLibrary,\n internalLibraries: new Set(),\n libraryEvidence: [],\n isLocalComponent: false,\n };\n }\n\n // It's a local component - resolve and analyze it\n const resolvedPath = resolveImportPath(importSource, contextFilePath);\n\n if (!resolvedPath) {\n // Could not resolve - might be external or invalid\n return {\n library: null,\n internalLibraries: new Set(),\n libraryEvidence: [],\n isLocalComponent: false,\n };\n }\n\n // Check cache\n const cacheKey = `${resolvedPath}::${componentName}`;\n if (componentLibraryCache.has(cacheKey)) {\n return componentLibraryCache.get(cacheKey)!;\n }\n\n // Resolve re-exports to find the actual component definition\n const resolvedExport = resolveExport(componentName, resolvedPath);\n const actualFilePath = resolvedExport?.filePath ?? resolvedPath;\n const actualComponentName = resolvedExport?.localName ?? componentName;\n\n // Analyze the component body\n const result = analyzeComponentLibraries(\n actualFilePath,\n actualComponentName,\n new Set([cacheKey]) // Track visited to prevent cycles\n );\n\n componentLibraryCache.set(cacheKey, result);\n return result;\n}\n\n/**\n * Recursively analyze a component's library usage\n */\nfunction analyzeComponentLibraries(\n filePath: string,\n componentName: string,\n visited: Set<string>\n): ComponentLibraryInfo {\n const styleInfo = parseComponentBody(filePath, componentName);\n\n if (!styleInfo) {\n return {\n library: null,\n internalLibraries: new Set(),\n libraryEvidence: [],\n isLocalComponent: true,\n };\n }\n\n const internalLibraries = new Set<LibraryName>();\n const libraryEvidence: Array<{\n componentName: string;\n library: LibraryName;\n }> = [];\n\n // Check direct library usage within this component\n if (styleInfo.directLibrary) {\n internalLibraries.add(styleInfo.directLibrary);\n }\n\n // Analyze each used component\n for (const usedComponent of styleInfo.usedComponents) {\n const usedLibrary = detectLibraryFromSource(usedComponent.importSource);\n\n if (usedLibrary) {\n // Direct import from a known library\n internalLibraries.add(usedLibrary);\n libraryEvidence.push({\n componentName: usedComponent.name,\n library: usedLibrary,\n });\n } else {\n // It's a local component - recurse into it\n const resolvedPath = resolveImportPath(\n usedComponent.importSource,\n filePath\n );\n\n if (resolvedPath) {\n const cacheKey = `${resolvedPath}::${usedComponent.name}`;\n\n // Skip if already visited (cycle detection)\n if (!visited.has(cacheKey)) {\n visited.add(cacheKey);\n\n // Check cache first\n let nestedInfo: ComponentLibraryInfo;\n if (componentLibraryCache.has(cacheKey)) {\n nestedInfo = componentLibraryCache.get(cacheKey)!;\n } else {\n // Resolve re-exports\n const resolvedExport = resolveExport(\n usedComponent.name,\n resolvedPath\n );\n const actualFilePath = resolvedExport?.filePath ?? resolvedPath;\n const actualComponentName =\n resolvedExport?.localName ?? usedComponent.name;\n\n nestedInfo = analyzeComponentLibraries(\n actualFilePath,\n actualComponentName,\n visited\n );\n componentLibraryCache.set(cacheKey, nestedInfo);\n }\n\n // Aggregate the nested component's libraries\n if (nestedInfo.library) {\n internalLibraries.add(nestedInfo.library);\n libraryEvidence.push({\n componentName: usedComponent.name,\n library: nestedInfo.library,\n });\n }\n\n for (const lib of nestedInfo.internalLibraries) {\n internalLibraries.add(lib);\n }\n\n // Add evidence from nested components\n for (const evidence of nestedInfo.libraryEvidence) {\n libraryEvidence.push({\n componentName: `${usedComponent.name} → ${evidence.componentName}`,\n library: evidence.library,\n });\n }\n }\n }\n }\n }\n\n return {\n library: styleInfo.directLibrary,\n internalLibraries,\n libraryEvidence,\n isLocalComponent: true,\n };\n}\n\n/**\n * Clear all caches (useful for testing or between ESLint runs)\n */\nexport function clearCache(): void {\n componentLibraryCache.clear();\n clearResolverCaches();\n}\n\n// Re-export types for convenience\nexport type { LibraryName };\n","/**\n * Rule: no-mixed-component-libraries\n *\n * Forbids using non-preferred UI component libraries. Reports errors at\n * the JSX usage site, including transitive usage through local components.\n *\n * Examples:\n * - <MuiButton> from @mui/material -> error at <MuiButton> usage\n * - <MyCard> that internally uses MUI -> error at <MyCard> usage\n */\n\nimport type { TSESTree } from \"@typescript-eslint/utils\";\nimport { createRule } from \"../utils/create-rule.js\";\nimport {\n getComponentLibrary,\n type LibraryName,\n} from \"../utils/import-graph.js\";\n\ntype MessageIds = \"nonPreferredLibrary\" | \"transitiveNonPreferred\";\ntype Options = [\n {\n /** The preferred UI library. Components from other libraries will be flagged. */\n preferred: LibraryName;\n /** Additional libraries to detect (defaults to common ones) */\n libraries?: LibraryName[];\n }\n];\n\n/**\n * Information about a component usage in the file\n */\ninterface ComponentUsage {\n /** The JSX element node (for error reporting) */\n node: TSESTree.JSXOpeningElement;\n /** Component name (e.g., \"Button\", \"MuiCard\") */\n componentName: string;\n /** Import source (e.g., \"@mui/material\", \"./components/cards\") */\n importSource: string;\n}\n\nexport default createRule<Options, MessageIds>({\n name: \"no-mixed-component-libraries\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Forbid using non-preferred UI component libraries. Reports at JSX usage sites, including transitive usage.\",\n },\n messages: {\n nonPreferredLibrary:\n \"Component <{{component}}> is from {{library}}, but {{preferred}} is the preferred library.\",\n transitiveNonPreferred:\n \"Component <{{component}}> internally uses {{libraries}} components ({{internalComponents}}). The preferred library is {{preferred}}.\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n preferred: {\n type: \"string\",\n enum: [\"shadcn\", \"mui\", \"chakra\", \"antd\"],\n description: \"The preferred UI library\",\n },\n libraries: {\n type: \"array\",\n items: {\n type: \"string\",\n enum: [\"shadcn\", \"mui\", \"chakra\", \"antd\"],\n },\n description: \"Libraries to detect (defaults to all)\",\n },\n },\n required: [\"preferred\"],\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [\n { preferred: \"shadcn\", libraries: [\"shadcn\", \"mui\", \"chakra\", \"antd\"] },\n ],\n create(context) {\n const options = context.options[0];\n const preferred = options.preferred;\n\n // Track imports: localName -> importSource\n const importMap = new Map<string, string>();\n\n // Track all component usages for analysis at Program:exit\n const componentUsages: ComponentUsage[] = [];\n\n return {\n ImportDeclaration(node) {\n const source = node.source.value as string;\n\n for (const spec of node.specifiers) {\n if (spec.type === \"ImportSpecifier\") {\n importMap.set(spec.local.name, source);\n } else if (spec.type === \"ImportDefaultSpecifier\") {\n importMap.set(spec.local.name, source);\n } else if (spec.type === \"ImportNamespaceSpecifier\") {\n importMap.set(spec.local.name, source);\n }\n }\n },\n\n JSXOpeningElement(node) {\n // Get the component name\n let componentName: string | null = null;\n\n if (node.name.type === \"JSXIdentifier\") {\n componentName = node.name.name;\n } else if (node.name.type === \"JSXMemberExpression\") {\n // Handle Namespace.Component (e.g., Modal.Header)\n let current = node.name.object;\n while (current.type === \"JSXMemberExpression\") {\n current = current.object;\n }\n if (current.type === \"JSXIdentifier\") {\n componentName = current.name;\n }\n }\n\n // Skip HTML elements (lowercase) and missing names\n if (!componentName || !/^[A-Z]/.test(componentName)) {\n return;\n }\n\n // Skip components that aren't imported (might be defined in same file)\n const importSource = importMap.get(componentName);\n if (!importSource) {\n return;\n }\n\n componentUsages.push({\n node,\n componentName,\n importSource,\n });\n },\n\n \"Program:exit\"() {\n const filename = context.filename || context.getFilename();\n\n for (const usage of componentUsages) {\n const libraryInfo = getComponentLibrary(\n filename,\n usage.componentName,\n usage.importSource\n );\n\n // Case 1: Direct import from non-preferred library\n if (libraryInfo.library && libraryInfo.library !== preferred) {\n context.report({\n node: usage.node,\n messageId: \"nonPreferredLibrary\",\n data: {\n component: usage.componentName,\n library: libraryInfo.library,\n preferred,\n },\n });\n continue;\n }\n\n // Case 2: Local component that uses non-preferred library internally\n if (\n libraryInfo.isLocalComponent &&\n libraryInfo.internalLibraries.size > 0\n ) {\n const nonPreferredLibs = [...libraryInfo.internalLibraries].filter(\n (lib) => lib !== preferred\n );\n\n if (nonPreferredLibs.length > 0) {\n // Get evidence of which internal components caused the violation\n const internalComponents = libraryInfo.libraryEvidence\n .filter((e) => e.library !== preferred)\n .map((e) => e.componentName)\n .slice(0, 3) // Limit to first 3 for readability\n .join(\", \");\n\n context.report({\n node: usage.node,\n messageId: \"transitiveNonPreferred\",\n data: {\n component: usage.componentName,\n libraries: nonPreferredLibs.join(\", \"),\n internalComponents: internalComponents || \"unknown\",\n preferred,\n },\n });\n }\n }\n }\n },\n };\n },\n});\n","/**\n * Rule: semantic\n *\n * LLM-powered semantic UI analysis using the project's styleguide.\n * This is the only rule that reads .uilint/styleguide.md.\n */\n\nimport { existsSync, readFileSync } from \"fs\";\nimport { spawnSync } from \"child_process\";\nimport { dirname, join, relative } from \"path\";\nimport { createRule } from \"../utils/create-rule.js\";\nimport {\n getCacheEntry,\n hashContentSync,\n setCacheEntry,\n type CachedIssue,\n} from \"../utils/cache.js\";\nimport { getStyleguide } from \"../utils/styleguide-loader.js\";\nimport { UILINT_DEFAULT_OLLAMA_MODEL } from \"uilint-core\";\nimport { buildSourceScanPrompt } from \"uilint-core\";\n\ntype MessageIds = \"semanticIssue\" | \"styleguideNotFound\" | \"analysisError\";\ntype Options = [\n {\n model?: string;\n styleguidePath?: string;\n }\n];\n\nexport default createRule<Options, MessageIds>({\n name: \"semantic\",\n meta: {\n type: \"suggestion\",\n docs: {\n description: \"LLM-powered semantic UI analysis using styleguide\",\n },\n messages: {\n semanticIssue: \"{{message}}\",\n styleguideNotFound:\n \"No styleguide found. Create .uilint/styleguide.md or specify styleguidePath.\",\n analysisError: \"Semantic analysis failed: {{error}}\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n model: {\n type: \"string\",\n description: \"Ollama model to use\",\n },\n styleguidePath: {\n type: \"string\",\n description: \"Path to styleguide file\",\n },\n },\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [{ model: UILINT_DEFAULT_OLLAMA_MODEL }],\n create(context) {\n const options = context.options[0] || {};\n const filePath = context.filename;\n const fileDir = dirname(filePath);\n\n // Get styleguide\n const { path: styleguidePath, content: styleguide } = getStyleguide(\n fileDir,\n options.styleguidePath\n );\n\n // Skip if no styleguide\n if (!styleguide) {\n console.error(\n `[uilint] Styleguide not found (styleguidePath=${String(\n options.styleguidePath ?? \"\"\n )}, startDir=${fileDir})`\n );\n\n return {\n Program(node) {\n context.report({\n node,\n messageId: \"styleguideNotFound\",\n });\n },\n };\n }\n\n // Read and hash file contents\n let fileContent: string;\n try {\n fileContent = readFileSync(filePath, \"utf-8\");\n } catch {\n console.error(`[uilint] Failed to read file ${filePath}`);\n return {\n Program(node) {\n context.report({\n node,\n messageId: \"analysisError\",\n data: { error: `Failed to read source file ${filePath}` },\n });\n },\n };\n }\n\n const fileHash = hashContentSync(fileContent);\n const styleguideHash = hashContentSync(styleguide);\n\n // Check cache\n const projectRoot = findProjectRoot(fileDir);\n const relativeFilePath = relative(projectRoot, filePath);\n const cached = getCacheEntry(\n projectRoot,\n relativeFilePath,\n fileHash,\n styleguideHash\n );\n\n const ENABLE_CACHE = false;\n if (ENABLE_CACHE && cached) {\n console.error(`[uilint] Cache hit for ${filePath}`);\n\n // Report cached issues\n return {\n Program(node) {\n for (const issue of cached.issues) {\n context.report({\n node,\n loc: { line: issue.line, column: issue.column || 0 },\n messageId: \"semanticIssue\",\n data: { message: issue.message },\n });\n }\n },\n };\n }\n\n // Cache miss: run sync analysis now (slow), cache, then report.\n ENABLE_CACHE &&\n console.error(\n `[uilint] Cache miss for ${filePath}, running semantic analysis`\n );\n\n return {\n Program(node) {\n const issues = runSemanticAnalysisSync(\n fileContent,\n styleguide,\n options.model || UILINT_DEFAULT_OLLAMA_MODEL,\n filePath\n );\n\n setCacheEntry(projectRoot, relativeFilePath, {\n fileHash,\n styleguideHash,\n issues,\n timestamp: Date.now(),\n });\n\n for (const issue of issues) {\n context.report({\n node,\n loc: { line: issue.line, column: issue.column || 0 },\n messageId: \"semanticIssue\",\n data: { message: issue.message },\n });\n }\n },\n };\n },\n});\n\n/**\n * Find project root by looking for package.json\n */\nfunction findProjectRoot(startDir: string): string {\n let dir = startDir;\n for (let i = 0; i < 20; i++) {\n if (existsSync(join(dir, \"package.json\"))) {\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return startDir;\n}\n\n/**\n * Run semantic analysis using Ollama (synchronously).\n *\n * Implementation detail:\n * - ESLint rules are synchronous.\n * - Blocking on a Promise (sleep-loop/Atomics) would also block Node's event loop,\n * preventing the HTTP request to Ollama from ever completing.\n * - To keep this simple & debuggable, we run the async LLM call in a child Node\n * process and synchronously wait for it to exit.\n */\nfunction runSemanticAnalysisSync(\n sourceCode: string,\n styleguide: string,\n model: string,\n filePath?: string\n): CachedIssue[] {\n const startTime = Date.now();\n const fileDisplay = filePath ? ` ${filePath}` : \"\";\n\n console.error(`[uilint] Starting semantic analysis (sync)${fileDisplay}`);\n console.error(`[uilint] Model: ${model}`);\n\n // Build prompt in-process (pure string building).\n const prompt = buildSourceScanPrompt(sourceCode, styleguide, {});\n\n // Avoid `uilint-core/node` exports *and* CJS resolution:\n // resolve the installed dependency by file URL relative to this plugin bundle.\n // When built, `import.meta.url` points at `.../uilint-eslint/dist/index.js`,\n // and the dependency lives at `.../uilint-eslint/node_modules/uilint-core/dist/node.js`.\n const coreNodeUrl = new URL(\n \"../node_modules/uilint-core/dist/node.js\",\n import.meta.url\n ).href;\n\n const childScript = `\n import * as coreNode from ${JSON.stringify(coreNodeUrl)};\n const { OllamaClient, logInfo, logWarning, createProgress, pc } = coreNode;\n const chunks = [];\n for await (const c of process.stdin) chunks.push(c);\n const input = JSON.parse(Buffer.concat(chunks).toString(\"utf8\"));\n const model = input.model;\n const prompt = input.prompt;\n\n const client = new OllamaClient({ model });\n const ok = await client.isAvailable();\n if (!ok) {\n logWarning(\"Ollama not available, skipping semantic analysis\");\n process.stdout.write(JSON.stringify({ issues: [] }));\n process.exit(0);\n }\n\n logInfo(\\`Ollama connected \\${pc.dim(\\`(model: \\${model})\\`)}\\`);\n const progress = createProgress(\"Analyzing with LLM...\");\n try {\n const response = await client.complete(prompt, {\n json: true,\n stream: true,\n onProgress: (latestLine) => {\n const maxLen = 60;\n const display =\n latestLine.length > maxLen\n ? latestLine.slice(0, maxLen) + \"…\"\n : latestLine;\n progress.update(\\`LLM: \\${pc.dim(display || \"...\")}\\`);\n },\n });\n progress.succeed(\"LLM complete\");\n process.stdout.write(response);\n } catch (e) {\n progress.fail(\\`LLM failed: \\${e instanceof Error ? e.message : String(e)}\\`);\n process.exit(1);\n }\n `;\n\n const child = spawnSync(\n process.execPath,\n [\"--input-type=module\", \"-e\", childScript],\n {\n input: JSON.stringify({ model, prompt }),\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"inherit\"],\n maxBuffer: 20 * 1024 * 1024,\n }\n );\n\n const elapsed = Date.now() - startTime;\n\n if (child.error) {\n console.error(\n `[uilint] Semantic analysis failed after ${elapsed}ms: ${child.error.message}`\n );\n return [];\n }\n\n if (typeof child.status === \"number\" && child.status !== 0) {\n console.error(\n `[uilint] Semantic analysis failed after ${elapsed}ms: child exited ${child.status}`\n );\n return [];\n }\n\n const responseText = (child.stdout || \"\").trim();\n if (!responseText) {\n console.error(\n `[uilint] Semantic analysis returned empty response (${elapsed}ms)`\n );\n return [];\n }\n\n try {\n const parsed = JSON.parse(responseText) as {\n issues?: Array<{ line?: number; column?: number; message?: string }>;\n };\n\n const issues = (parsed.issues || []).map((issue) => ({\n line: issue.line || 1,\n column: issue.column,\n message: issue.message || \"Semantic issue detected\",\n ruleId: \"uilint/semantic\",\n severity: 1 as const,\n }));\n\n if (issues.length > 0) {\n console.error(`[uilint] Found ${issues.length} issue(s) (${elapsed}ms)`);\n } else {\n console.error(`[uilint] No issues found (${elapsed}ms)`);\n }\n\n return issues;\n } catch (e) {\n console.error(\n `[uilint] Semantic analysis failed to parse response after ${elapsed}ms: ${\n e instanceof Error ? e.message : String(e)\n }`\n );\n return [];\n }\n}\n","/**\n * File-hash based caching for LLM semantic rule\n *\n * Uses xxhash for fast hashing of file contents.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\n\n// Lazy-loaded xxhash\nlet xxhashInstance: Awaited<\n ReturnType<typeof import(\"xxhash-wasm\")[\"default\"]>\n> | null = null;\n\nasync function getXxhash() {\n if (!xxhashInstance) {\n const xxhash = await import(\"xxhash-wasm\");\n xxhashInstance = await xxhash.default();\n }\n return xxhashInstance;\n}\n\n/**\n * Synchronous hash using a simple djb2 algorithm (fallback when xxhash not available)\n */\nfunction djb2Hash(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = (hash * 33) ^ str.charCodeAt(i);\n }\n return (hash >>> 0).toString(16);\n}\n\n/**\n * Hash content using xxhash (async) or djb2 (sync fallback)\n */\nexport async function hashContent(content: string): Promise<string> {\n try {\n const xxhash = await getXxhash();\n return xxhash.h64ToString(content);\n } catch {\n return djb2Hash(content);\n }\n}\n\n/**\n * Synchronous hash for when async is not possible\n */\nexport function hashContentSync(content: string): string {\n return djb2Hash(content);\n}\n\nexport interface CacheEntry {\n fileHash: string;\n styleguideHash: string;\n issues: CachedIssue[];\n timestamp: number;\n}\n\nexport interface CachedIssue {\n line: number;\n column?: number;\n message: string;\n ruleId: string;\n severity: 1 | 2; // 1 = warn, 2 = error\n}\n\nexport interface CacheStore {\n version: number;\n entries: Record<string, CacheEntry>;\n}\n\nconst CACHE_VERSION = 1;\nconst CACHE_FILE = \".uilint/.cache/eslint-semantic.json\";\n\n/**\n * Get the cache file path for a project\n */\nexport function getCachePath(projectRoot: string): string {\n return join(projectRoot, CACHE_FILE);\n}\n\n/**\n * Load the cache store\n */\nexport function loadCache(projectRoot: string): CacheStore {\n const cachePath = getCachePath(projectRoot);\n\n if (!existsSync(cachePath)) {\n return { version: CACHE_VERSION, entries: {} };\n }\n\n try {\n const content = readFileSync(cachePath, \"utf-8\");\n const cache = JSON.parse(content) as CacheStore;\n\n // Invalidate if version mismatch\n if (cache.version !== CACHE_VERSION) {\n return { version: CACHE_VERSION, entries: {} };\n }\n\n return cache;\n } catch {\n return { version: CACHE_VERSION, entries: {} };\n }\n}\n\n/**\n * Save the cache store\n */\nexport function saveCache(projectRoot: string, cache: CacheStore): void {\n const cachePath = getCachePath(projectRoot);\n\n try {\n const cacheDir = dirname(cachePath);\n if (!existsSync(cacheDir)) {\n mkdirSync(cacheDir, { recursive: true });\n }\n\n writeFileSync(cachePath, JSON.stringify(cache, null, 2), \"utf-8\");\n } catch {\n // Silently fail - caching is optional\n }\n}\n\n/**\n * Get cached entry for a file\n */\nexport function getCacheEntry(\n projectRoot: string,\n filePath: string,\n fileHash: string,\n styleguideHash: string\n): CacheEntry | null {\n const cache = loadCache(projectRoot);\n const entry = cache.entries[filePath];\n\n if (!entry) return null;\n\n // Check if hashes match\n if (entry.fileHash !== fileHash || entry.styleguideHash !== styleguideHash) {\n return null;\n }\n\n return entry;\n}\n\n/**\n * Set cached entry for a file\n */\nexport function setCacheEntry(\n projectRoot: string,\n filePath: string,\n entry: CacheEntry\n): void {\n const cache = loadCache(projectRoot);\n cache.entries[filePath] = entry;\n saveCache(projectRoot, cache);\n}\n\n/**\n * Clear cache for a specific file\n */\nexport function clearCacheEntry(projectRoot: string, filePath: string): void {\n const cache = loadCache(projectRoot);\n delete cache.entries[filePath];\n saveCache(projectRoot, cache);\n}\n\n/**\n * Clear entire cache\n */\nexport function clearCache(projectRoot: string): void {\n saveCache(projectRoot, { version: CACHE_VERSION, entries: {} });\n}\n","/**\n * Styleguide loader for the LLM semantic rule\n *\n * Only the semantic rule reads the styleguide - static rules use ESLint options.\n */\n\nimport { existsSync, readFileSync } from \"fs\";\nimport { dirname, isAbsolute, join, resolve } from \"path\";\n\nconst DEFAULT_STYLEGUIDE_PATHS = [\n \".uilint/styleguide.md\",\n \".uilint/styleguide.yaml\",\n \".uilint/styleguide.yml\",\n];\n\n/**\n * Find workspace root by walking up looking for pnpm-workspace.yaml, package.json, or .git\n */\nfunction findWorkspaceRoot(startDir: string): string {\n let dir = startDir;\n for (let i = 0; i < 20; i++) {\n if (\n existsSync(join(dir, \"pnpm-workspace.yaml\")) ||\n existsSync(join(dir, \".git\"))\n ) {\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return startDir;\n}\n\n/**\n * Find the nearest package root (directory containing package.json),\n * stopping at the workspace root.\n */\nfunction findNearestPackageRoot(\n startDir: string,\n workspaceRoot: string\n): string {\n let dir = startDir;\n for (let i = 0; i < 30; i++) {\n if (existsSync(join(dir, \"package.json\"))) return dir;\n if (dir === workspaceRoot) break;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return startDir;\n}\n\n/**\n * Find the styleguide file path\n */\nexport function findStyleguidePath(\n startDir: string,\n explicitPath?: string\n): string | null {\n // Explicit path takes precedence\n if (explicitPath) {\n if (isAbsolute(explicitPath)) {\n return existsSync(explicitPath) ? explicitPath : null;\n }\n\n // For relative explicit paths, try:\n // 1) relative to the file dir (back-compat)\n // 2) relative to the nearest package root (typical \"project root\")\n // 3) relative to workspace root (monorepo root)\n const workspaceRoot = findWorkspaceRoot(startDir);\n const packageRoot = findNearestPackageRoot(startDir, workspaceRoot);\n\n const candidates = [\n resolve(startDir, explicitPath),\n resolve(packageRoot, explicitPath),\n resolve(workspaceRoot, explicitPath),\n ];\n\n for (const p of candidates) {\n if (existsSync(p)) return p;\n }\n\n return null;\n }\n\n // Check from start dir up to workspace root\n const workspaceRoot = findWorkspaceRoot(startDir);\n let dir = startDir;\n\n while (true) {\n for (const relativePath of DEFAULT_STYLEGUIDE_PATHS) {\n const fullPath = join(dir, relativePath);\n if (existsSync(fullPath)) {\n return fullPath;\n }\n }\n\n // Stop at workspace root\n if (dir === workspaceRoot) break;\n\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n return null;\n}\n\n/**\n * Load styleguide content from file\n */\nexport function loadStyleguide(\n startDir: string,\n explicitPath?: string\n): string | null {\n const path = findStyleguidePath(startDir, explicitPath);\n if (!path) return null;\n\n try {\n return readFileSync(path, \"utf-8\");\n } catch {\n return null;\n }\n}\n\n/**\n * Get styleguide path and content\n */\nexport function getStyleguide(\n startDir: string,\n explicitPath?: string\n): { path: string | null; content: string | null } {\n const path = findStyleguidePath(startDir, explicitPath);\n if (!path) return { path: null, content: null };\n\n try {\n const content = readFileSync(path, \"utf-8\");\n return { path, content };\n } catch {\n return { path, content: null };\n }\n}\n","/**\n * Rule Registry\n *\n * Central registry of all UILint ESLint rules with metadata for CLI tooling.\n * This allows the installer to auto-discover available rules and present them\n * to the user with descriptions.\n */\n\nexport interface RuleMetadata {\n /** Rule identifier (e.g., \"no-arbitrary-tailwind\") */\n id: string;\n /** Display name for CLI */\n name: string;\n /** Short description for CLI selection prompts */\n description: string;\n /** Default severity level */\n defaultSeverity: \"error\" | \"warn\" | \"off\";\n /** Default options for the rule */\n defaultOptions?: unknown[];\n /** Whether this rule requires a styleguide file */\n requiresStyleguide?: boolean;\n /** Category for grouping */\n category: \"static\" | \"semantic\";\n}\n\n/**\n * Registry of all available UILint ESLint rules\n *\n * When adding a new rule:\n * 1. Add the rule implementation to src/rules/\n * 2. Add an entry here with metadata\n * 3. Export the rule from src/index.ts\n * 4. The CLI installer will automatically discover and offer it\n */\nexport const ruleRegistry: RuleMetadata[] = [\n {\n id: \"no-arbitrary-tailwind\",\n name: \"No Arbitrary Tailwind\",\n description: \"Forbid arbitrary values like w-[123px], bg-[#fff]\",\n defaultSeverity: \"error\",\n category: \"static\",\n },\n {\n id: \"consistent-spacing\",\n name: \"Consistent Spacing\",\n description: \"Enforce spacing scale (no magic numbers in gap/padding)\",\n defaultSeverity: \"warn\",\n defaultOptions: [{ scale: [0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16] }],\n category: \"static\",\n },\n {\n id: \"consistent-dark-mode\",\n name: \"Consistent Dark Mode\",\n description:\n \"Ensure consistent dark: theming (error on mix, warn on missing)\",\n defaultSeverity: \"error\",\n defaultOptions: [{ warnOnMissingDarkMode: true }],\n category: \"static\",\n },\n {\n id: \"no-direct-store-import\",\n name: \"No Direct Store Import\",\n description: \"Forbid direct Zustand store imports (use context hooks)\",\n defaultSeverity: \"warn\",\n defaultOptions: [{ storePattern: \"use*Store\" }],\n category: \"static\",\n },\n {\n id: \"prefer-zustand-state-management\",\n name: \"Prefer Zustand State Management\",\n description:\n \"Detect excessive useState/useReducer/useContext; suggest Zustand\",\n defaultSeverity: \"warn\",\n defaultOptions: [\n {\n maxStateHooks: 3,\n countUseState: true,\n countUseReducer: true,\n countUseContext: true,\n },\n ],\n category: \"static\",\n },\n {\n id: \"no-mixed-component-libraries\",\n name: \"No Mixed Component Libraries\",\n description: \"Forbid mixing component libraries (e.g., shadcn + MUI)\",\n defaultSeverity: \"error\",\n defaultOptions: [{ libraries: [\"shadcn\", \"mui\"] }],\n category: \"static\",\n },\n {\n id: \"semantic\",\n name: \"Semantic Analysis\",\n description: \"LLM-powered semantic UI analysis using your styleguide\",\n defaultSeverity: \"warn\",\n defaultOptions: [\n { model: \"qwen3-coder:30b\", styleguidePath: \".uilint/styleguide.md\" },\n ],\n requiresStyleguide: true,\n category: \"semantic\",\n },\n];\n\n/**\n * Get rule metadata by ID\n */\nexport function getRuleMetadata(id: string): RuleMetadata | undefined {\n return ruleRegistry.find((rule) => rule.id === id);\n}\n\n/**\n * Get all rules in a category\n */\nexport function getRulesByCategory(\n category: \"static\" | \"semantic\"\n): RuleMetadata[] {\n return ruleRegistry.filter((rule) => rule.category === category);\n}\n","/**\n * UILint ESLint Plugin\n *\n * THIS FILE IS AUTO-GENERATED from src/rule-registry.ts.\n * Do not edit by hand. Run: pnpm -C packages/uilint-eslint generate:index\n */\n\nimport type { Linter } from \"eslint\";\nimport noArbitraryTailwind from \"./rules/no-arbitrary-tailwind.js\";\nimport consistentSpacing from \"./rules/consistent-spacing.js\";\nimport consistentDarkMode from \"./rules/consistent-dark-mode.js\";\nimport noDirectStoreImport from \"./rules/no-direct-store-import.js\";\nimport preferZustandStateManagement from \"./rules/prefer-zustand-state-management.js\";\nimport noMixedComponentLibraries from \"./rules/no-mixed-component-libraries.js\";\nimport semantic from \"./rules/semantic.js\";\n\n/**\n * All available rules\n */\nconst rules = {\n \"no-arbitrary-tailwind\": noArbitraryTailwind,\n \"consistent-spacing\": consistentSpacing,\n \"consistent-dark-mode\": consistentDarkMode,\n \"no-direct-store-import\": noDirectStoreImport,\n \"prefer-zustand-state-management\": preferZustandStateManagement,\n \"no-mixed-component-libraries\": noMixedComponentLibraries,\n \"semantic\": semantic,\n};\n\n// Package version (injected at build time or fallback)\nconst version = \"0.1.0\";\n\n/**\n * Plugin metadata\n */\nconst meta = {\n name: \"uilint\",\n version,\n};\n\n/**\n * The ESLint plugin object\n */\nconst plugin = {\n meta,\n rules,\n};\n\n/**\n * Shared language options for all configs\n */\nconst jsxLanguageOptions: Linter.Config[\"languageOptions\"] = {\n parserOptions: {\n ecmaFeatures: {\n jsx: true,\n },\n },\n};\n\n/**\n * Recommended config - static rules only\n *\n * Usage:\n * ```js\n * import uilint from 'uilint-eslint';\n * export default [uilint.configs.recommended];\n * ```\n */\nconst recommendedConfig: Linter.Config = {\n name: \"uilint/recommended\",\n plugins: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n uilint: plugin as any,\n },\n languageOptions: jsxLanguageOptions,\n rules: {\n \"uilint/no-arbitrary-tailwind\": \"error\",\n \"uilint/consistent-spacing\": [\"warn\", ...[\n {\n \"scale\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6,\n 8,\n 10,\n 12,\n 16\n ]\n }\n ]],\n \"uilint/consistent-dark-mode\": [\"error\", ...[\n {\n \"warnOnMissingDarkMode\": true\n }\n ]],\n \"uilint/no-direct-store-import\": [\"warn\", ...[\n {\n \"storePattern\": \"use*Store\"\n }\n ]],\n \"uilint/prefer-zustand-state-management\": [\"warn\", ...[\n {\n \"maxStateHooks\": 3,\n \"countUseState\": true,\n \"countUseReducer\": true,\n \"countUseContext\": true\n }\n ]],\n \"uilint/no-mixed-component-libraries\": [\"error\", ...[\n {\n \"libraries\": [\n \"shadcn\",\n \"mui\"\n ]\n }\n ]],\n },\n};\n\n/**\n * Strict config - static rules + semantic rules\n *\n * Usage:\n * ```js\n * import uilint from 'uilint-eslint';\n * export default [uilint.configs.strict];\n * ```\n */\nconst strictConfig: Linter.Config = {\n name: \"uilint/strict\",\n plugins: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n uilint: plugin as any,\n },\n languageOptions: jsxLanguageOptions,\n rules: {\n \"uilint/no-arbitrary-tailwind\": \"error\",\n \"uilint/consistent-spacing\": [\"warn\", ...[\n {\n \"scale\": [\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6,\n 8,\n 10,\n 12,\n 16\n ]\n }\n ]],\n \"uilint/consistent-dark-mode\": [\"error\", ...[\n {\n \"warnOnMissingDarkMode\": true\n }\n ]],\n \"uilint/no-direct-store-import\": [\"warn\", ...[\n {\n \"storePattern\": \"use*Store\"\n }\n ]],\n \"uilint/prefer-zustand-state-management\": [\"warn\", ...[\n {\n \"maxStateHooks\": 3,\n \"countUseState\": true,\n \"countUseReducer\": true,\n \"countUseContext\": true\n }\n ]],\n \"uilint/no-mixed-component-libraries\": [\"error\", ...[\n {\n \"libraries\": [\n \"shadcn\",\n \"mui\"\n ]\n }\n ]],\n \"uilint/semantic\": [\"warn\", ...[\n {\n \"model\": \"qwen3-coder:30b\",\n \"styleguidePath\": \".uilint/styleguide.md\"\n }\n ]],\n },\n};\n\n/**\n * Pre-configured configs\n */\nconst configs: Record<string, Linter.Config> = {\n recommended: recommendedConfig,\n strict: strictConfig,\n};\n\n/**\n * UILint ESLint export interface\n */\nexport interface UILintESLint {\n meta: typeof meta;\n plugin: typeof plugin;\n rules: typeof rules;\n configs: Record<string, Linter.Config>;\n}\n\n/**\n * Default export for ESLint flat config\n */\nconst uilintEslint: UILintESLint = {\n meta,\n plugin,\n rules,\n configs,\n};\n\nexport default uilintEslint;\n\n// Named exports for convenience\nexport { plugin, rules, configs, meta };\n\n// Re-export utilities for custom rule creation\nexport { createRule } from \"./utils/create-rule.js\";\nexport {\n loadStyleguide,\n findStyleguidePath,\n getStyleguide,\n} from \"./utils/styleguide-loader.js\";\nexport {\n hashContent,\n hashContentSync,\n getCacheEntry,\n setCacheEntry,\n clearCache,\n clearCacheEntry,\n loadCache,\n saveCache,\n type CacheEntry,\n type CachedIssue,\n type CacheStore,\n} from \"./utils/cache.js\";\n\n// Re-export rule registry for CLI tooling\nexport {\n ruleRegistry,\n getRuleMetadata,\n getRulesByCategory,\n type RuleMetadata,\n} from \"./rule-registry.js\";\n"],"mappings":"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","names":["checkClassString","existsSync","readFileSync","dirname","join","existsSync","readFileSync","dirname","join","existsSync","readFileSync","dirname","join","workspaceRoot","dirname","readFileSync","findProjectRoot","existsSync","join"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uilint-eslint",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.22",
|
|
4
4
|
"description": "ESLint plugin for UILint - AI-powered UI consistency checking",
|
|
5
5
|
"author": "Peter Suggate",
|
|
6
6
|
"repository": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@typescript-eslint/typescript-estree": "^8.35.1",
|
|
34
34
|
"@typescript-eslint/utils": "^8.35.1",
|
|
35
35
|
"oxc-resolver": "^11.0.0",
|
|
36
|
-
"uilint-core": "^0.1.
|
|
36
|
+
"uilint-core": "^0.1.52",
|
|
37
37
|
"xxhash-wasm": "^1.1.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|