{"_id":"@brandplan/eslint-plugin","_rev":"3-c85ebdcee418484d19bc9c3193decc1b","name":"@brandplan/eslint-plugin","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@brandplan/eslint-plugin","version":"0.1.0","keywords":["eslint","eslintplugin","brandplan","design-tokens","tailwindcss"],"license":"MIT","_id":"@brandplan/eslint-plugin@0.1.0","maintainers":[{"name":"ibrahim-bayer","email":"ibrahimbayer@gmail.com"}],"homepage":"https://github.com/ibrahim-bayer/brandplan#readme","bugs":{"url":"https://github.com/ibrahim-bayer/brandplan/issues"},"dist":{"shasum":"9e16196b2e18df54bdd793017ab32292d518e135","tarball":"https://registry.npmjs.org/@brandplan/eslint-plugin/-/eslint-plugin-0.1.0.tgz","fileCount":6,"integrity":"sha512-h2Ar17SDjlci+UqhKeSC4izbOlzRyKN/mZveZZoPTcngEUv/CXEWsGIB46tQcfWMwoN8XX44kSOwXeLefh1TJg==","signatures":[{"sig":"MEQCIGqUirjUHULOoxOTHbrlACBonJ+Xyk9w6hkrmgySlx77AiBIi1FTRxgg4GAustyIIcxXVH1eW9HrQ55PcQINLwiYGg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37270},"main":"./dist/index.js","type":"module","_from":"file:brandplan-eslint-plugin-0.1.0.tgz","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","test:watch":"vitest"},"_npmUser":{"name":"ibrahim-bayer","email":"ibrahimbayer@gmail.com"},"_resolved":"/private/var/folders/fs/bhvlltpx1_n5_n60yrp0gshw0000gn/T/989474304ffc41e2a20624f54ff7075c/brandplan-eslint-plugin-0.1.0.tgz","_integrity":"sha512-h2Ar17SDjlci+UqhKeSC4izbOlzRyKN/mZveZZoPTcngEUv/CXEWsGIB46tQcfWMwoN8XX44kSOwXeLefh1TJg==","repository":{"url":"git+https://github.com/ibrahim-bayer/brandplan.git","type":"git","directory":"packages/eslint-plugin"},"_npmVersion":"10.8.2","description":"ESLint plugin to enforce BrandPlan design token usage and prevent visual drift","directories":{},"_nodeVersion":"18.20.8","dependencies":{"picomatch":"^4.0.3"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.17.0","@types/eslint":"^9.6.1","@types/picomatch":"^4.0.2"},"peerDependencies":{"eslint":"^8.0.0 || ^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin_0.1.0_1765981487482_0.9016575563003617","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@brandplan/eslint-plugin","version":"0.1.1","keywords":["eslint","eslintplugin","brandplan","design-tokens","tailwindcss"],"license":"MIT","_id":"@brandplan/eslint-plugin@0.1.1","maintainers":[{"name":"ibrahim-bayer","email":"ibrahimbayer@gmail.com"}],"homepage":"https://github.com/ibrahim-bayer/brandplan#readme","bugs":{"url":"https://github.com/ibrahim-bayer/brandplan/issues"},"dist":{"shasum":"be3a53afa1d3958c4471317ecbb65220271782e8","tarball":"https://registry.npmjs.org/@brandplan/eslint-plugin/-/eslint-plugin-0.1.1.tgz","fileCount":5,"integrity":"sha512-RoeWuCnbOOJr524/ELDDVRflrpAAyqRFg5r19PwiNibFISOSzYu6JorYpkiHdI3IumOr0tNgvySlqfhEI9orzQ==","signatures":[{"sig":"MEQCIGSPbSumvJLqbsz0ja3DYBpp+sEC8imkoXdulTtZ086tAiATCpkYxhxaPdGlXG++KTNHPQsxm26+ozIDFG0JaFHTLw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36698},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20.9.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"430a913ed5516b77b989d105ff23560f9e79ca23","scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","test:watch":"vitest"},"_npmUser":{"name":"ibrahim-bayer","email":"ibrahimbayer@gmail.com"},"repository":{"url":"git+https://github.com/ibrahim-bayer/brandplan.git","type":"git","directory":"packages/eslint-plugin"},"_npmVersion":"10.8.2","description":"ESLint plugin to enforce BrandPlan design token usage and prevent visual drift","directories":{},"_nodeVersion":"20.19.4","dependencies":{"picomatch":"^4.0.3"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.17.0","@types/eslint":"^9.6.1","@types/picomatch":"^4.0.2"},"peerDependencies":{"eslint":"^8.0.0 || ^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin_0.1.1_1766426660928_0.4451706084200806","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@brandplan/eslint-plugin","version":"0.1.2","description":"ESLint plugin to enforce BrandPlan design token usage and prevent visual drift","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","license":"MIT","engines":{"node":">=20.9.0"},"repository":{"type":"git","url":"git+https://github.com/ibrahim-bayer/brandplan.git","directory":"packages/eslint-plugin"},"homepage":"https://github.com/ibrahim-bayer/brandplan#readme","bugs":{"url":"https://github.com/ibrahim-bayer/brandplan/issues"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsup","test":"vitest run","test:watch":"vitest","lint":"eslint src"},"peerDependencies":{"eslint":"^8.0.0 || ^9.0.0"},"devDependencies":{"@types/eslint":"^9.6.1","@types/picomatch":"^4.0.2","eslint":"^9.17.0"},"keywords":["eslint","eslintplugin","brandplan","design-tokens","tailwindcss"],"dependencies":{"picomatch":"^4.0.3"},"_id":"@brandplan/eslint-plugin@0.1.2","gitHead":"b6390dea0c90d1afb7ccf7261b69fef19f23c7b4","_nodeVersion":"20.19.4","_npmVersion":"10.8.2","dist":{"integrity":"sha512-ilv9p6wzYcUiB5jC+QQrqA1Q/T5nS9d1qPO/Qzwiadu6509ZYvZII+1IGQcBdJNAy9OevISPmx/0bkD/oOV/lg==","shasum":"8ddc5982d675c85250d9831727927aedaf6decff","tarball":"https://registry.npmjs.org/@brandplan/eslint-plugin/-/eslint-plugin-0.1.2.tgz","fileCount":5,"unpackedSize":36698,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCrdNiClsTbWSxYhR3PsnsaaQrpyW3T//v+rn9aqeL4wAIhAMC9rMXUz9RtU5HEryA2r/CJB7CKRM5MqxkbPtWEhjwL"}]},"_npmUser":{"name":"ibrahim-bayer","email":"ibrahimbayer@gmail.com"},"directories":{},"maintainers":[{"name":"ibrahim-bayer","email":"ibrahimbayer@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/eslint-plugin_0.1.2_1766428167430_0.2106950207026559"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-17T14:24:47.389Z","modified":"2025-12-22T18:29:27.781Z","0.1.0":"2025-12-17T14:24:47.629Z","0.1.1":"2025-12-22T18:04:21.089Z","0.1.2":"2025-12-22T18:29:27.568Z"},"bugs":{"url":"https://github.com/ibrahim-bayer/brandplan/issues"},"license":"MIT","homepage":"https://github.com/ibrahim-bayer/brandplan#readme","keywords":["eslint","eslintplugin","brandplan","design-tokens","tailwindcss"],"repository":{"type":"git","url":"git+https://github.com/ibrahim-bayer/brandplan.git","directory":"packages/eslint-plugin"},"description":"ESLint plugin to enforce BrandPlan design token usage and prevent visual drift","maintainers":[{"name":"ibrahim-bayer","email":"ibrahimbayer@gmail.com"}],"readme":"# @brandplan/eslint-plugin\n\nESLint plugin to enforce BrandPlan design token usage and prevent visual drift.\n\n## Installation\n\n```bash\npnpm add -D @brandplan/eslint-plugin\n```\n\n## Usage\n\n### Basic Configuration\n\n```javascript\n// eslint.config.js\nimport brandplan from '@brandplan/eslint-plugin';\n\nexport default [\n  {\n    files: ['**/*.tsx'],\n    plugins: {\n      '@brandplan': brandplan,\n    },\n    rules: {\n      '@brandplan/brand-classnames-only': 'error',\n      '@brandplan/brand-margin-policy': 'error',\n    },\n  },\n];\n```\n\n### Recommended Configuration\n\nUse the recommended config to enable all rules:\n\n```javascript\n// eslint.config.js\nimport brandplan from '@brandplan/eslint-plugin';\n\nexport default [\n  {\n    files: ['**/*.tsx'],\n    plugins: {\n      '@brandplan': brandplan,\n    },\n    ...brandplan.configs.recommended,\n  },\n];\n```\n\n## Rules\n\n### `brand-classnames-only`\n\nEnforces brand-prefixed utilities for design-critical properties and allows layout utilities only.\n\n**Blocked (design-critical, non-brand):**\n- Spacing: `p-4`, `m-2`, `gap-6`\n- Radius: `rounded-lg`, `rounded-md`\n- Colors: `bg-slate-100`, `text-white`, `border-gray-300`\n- Shadows: `shadow-md`, `shadow-lg`\n\n**Allowed:**\n- Layout utilities: `flex`, `grid`, `w-full`, `h-screen`, `max-w-md`, `items-center`, `justify-between`\n- Brand utilities: `p-brand-4`, `rounded-brand-md`, `bg-brand-surface-0`, `text-brand-text-primary`\n\n**Examples:**\n\n```tsx\n// ❌ Blocked\n<div className=\"p-4 rounded-lg bg-white\" />\n\n// ✅ Allowed\n<div className=\"p-brand-4 rounded-brand-md bg-brand-surface-0 flex w-full\" />\n```\n\n### `brand-margin-policy`\n\nEnforces margin utilities only on semantic layout elements.\n\n**Allowed elements for margin:**\n- `<main>`\n- `<header>`\n- `<footer>`\n- `<section>` (configurable)\n\n**Blocked elements for margin:**\n- All other elements (div, span, Card, Button, etc.)\n\n**Configuration:**\n\n```javascript\n{\n  rules: {\n    '@brandplan/brand-margin-policy': ['error', {\n      allowSection: true  // Allow margin on <section> elements\n    }]\n  }\n}\n```\n\n**Examples:**\n\n```tsx\n// ❌ Blocked - div with margin\n<div className=\"m-brand-4\">Content</div>\n\n// ❌ Blocked - component with margin\n<Card className=\"mt-brand-2\">Content</Card>\n\n// ✅ Allowed - semantic element with margin\n<main className=\"m-brand-4\">Content</main>\n\n// ✅ Allowed - div without margin\n<div className=\"p-brand-4 flex gap-brand-2\">Content</div>\n\n// ✅ Allowed - header with margin\n<header className=\"mb-brand-2 px-brand-4\">Header</header>\n```\n\n**Rationale:**\n\nMargin creates external spacing that affects layout relationships between components. By restricting margins to semantic layout elements only, BrandPlan:\n- Prevents margin conflicts and collapsing margin bugs\n- Encourages proper component composition with gap-brand-*\n- Keeps components predictable and reusable\n- Makes layouts explicit in semantic structure\n\n**Alternatives to margin:**\n- Use `gap-brand-*` for spacing between flex/grid children\n- Use `p-brand-*` (padding) for internal spacing\n- Wrap content in semantic layout elements when margin is needed\n\n## Advanced Usage\n\n### Complex className Expressions\n\nBoth rules parse various className patterns:\n\n```tsx\n// String literals\n<div className=\"flex p-brand-4\" />\n\n// Template literals\n<div className={`flex ${active && \"bg-brand-primary\"}`} />\n\n// cn() / clsx() helper\n<div className={cn(\"flex\", isActive && \"bg-brand-primary\")} />\n\n// Arrays\n<div className={clsx([\"flex\", \"p-brand-4\"])} />\n\n// Conditional expressions\n<div className={hasMargin ? \"m-brand-4\" : \"p-brand-4\"} />\n```\n\nAll patterns are properly analyzed for violations.\n\n## Error Messages\n\nThe plugin provides helpful error messages with suggestions:\n\n```\nNon-brand utility \"p-4\" is not allowed. Use brand-prefixed utilities (e.g., p-brand-4) or layout utilities only.\n\nBrandPlan margin utilities are only allowed on semantic layout elements (main, header, footer). Consider using gap-brand-* or padding instead.\n```\n\n## Integration with BrandPlan Packages\n\nThis plugin works together with:\n- **@brandplan/core**: Generates brand token CSS\n- **@brandplan/ui**: React components using brand tokens\n\nThe ESLint plugin enforces what the other packages provide, creating a complete system that prevents visual drift at build time.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}