website refactor
This commit is contained in:
@@ -45,7 +45,6 @@ const cleanErrorHandling = require('./clean-error-handling');
|
||||
const servicesImplementContract = require('./services-implement-contract');
|
||||
const serverActionsReturnResult = require('./server-actions-return-result');
|
||||
const serverActionsInterface = require('./server-actions-interface');
|
||||
const noGenericUiPrimitivesInComponents = require('./no-generic-ui-primitives-in-components');
|
||||
|
||||
module.exports = {
|
||||
rules: {
|
||||
@@ -154,7 +153,6 @@ module.exports = {
|
||||
'ui-element-purity': require('./ui-element-purity'),
|
||||
'no-nextjs-imports-in-ui': require('./no-nextjs-imports-in-ui'),
|
||||
'component-classification': require('./component-classification'),
|
||||
'no-generic-ui-primitives-in-components': noGenericUiPrimitivesInComponents,
|
||||
|
||||
// Route Configuration Rules
|
||||
'no-hardcoded-routes': require('./no-hardcoded-routes'),
|
||||
@@ -271,7 +269,6 @@ module.exports = {
|
||||
'gridpilot-rules/ui-element-purity': 'error',
|
||||
'gridpilot-rules/no-nextjs-imports-in-ui': 'error',
|
||||
'gridpilot-rules/component-classification': 'error',
|
||||
'gridpilot-rules/no-generic-ui-primitives-in-components': 'error',
|
||||
|
||||
// Route Configuration Rules
|
||||
'gridpilot-rules/no-hardcoded-routes': 'error',
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/**
|
||||
* ESLint rule to ban usage of generic UI primitives in components
|
||||
*
|
||||
* Generic primitives like Box and Surface should only be used in the ui/ layer
|
||||
* to build semantic UI elements. Components should use those semantic elements.
|
||||
*
|
||||
* Rationale:
|
||||
* - Encourages use of semantic UI components
|
||||
* - Maintains architectural boundaries
|
||||
* - Improves consistency across the application
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Ban usage of generic UI primitives in components',
|
||||
category: 'Architecture',
|
||||
recommended: true,
|
||||
},
|
||||
fixable: null,
|
||||
schema: [],
|
||||
messages: {
|
||||
noGenericPrimitive: 'Generic UI primitive or wrapper "{{name}}" is not allowed in components. Primitives (Box, Surface) and generic wrappers (Layout, Container) are internal to the UI layer. Use semantic UI elements from @/ui instead (e.g., Card, Section, Table, Stack, Grid). If a semantic element is missing, create one in apps/website/ui/ using primitives.',
|
||||
noPrimitiveExport: 'Do not re-export primitives from the UI layer. Primitives should remain internal to apps/website/ui/primitives/.',
|
||||
noClassName: 'The "className" prop is not allowed in components. Styling must be encapsulated within UI elements in apps/website/ui/. Use semantic UI elements or create a new one if you need custom styling.',
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const filename = context.getFilename();
|
||||
|
||||
// Only run for files under /components/ (and *.ts/*.tsx)
|
||||
const isComponent = filename.includes('/components/') && (filename.endsWith('.ts') || filename.endsWith('.tsx'));
|
||||
|
||||
// Check for re-exports in the UI layer (excluding primitives themselves)
|
||||
const isUiLayer = filename.includes('/ui/') && !filename.includes('/ui/primitives/');
|
||||
|
||||
return {
|
||||
ImportDeclaration(node) {
|
||||
if (!isComponent) return;
|
||||
|
||||
const importPath = node.source.value;
|
||||
|
||||
// Check if it's an import from the UI primitives layer
|
||||
const isPrimitiveImport =
|
||||
importPath.includes('/ui/primitives') ||
|
||||
importPath.startsWith('@/ui/primitives') ||
|
||||
// Legacy direct paths
|
||||
importPath.endsWith('/ui/Box') ||
|
||||
importPath.endsWith('/ui/Surface') ||
|
||||
importPath.endsWith('/ui/Layout') ||
|
||||
importPath.endsWith('/ui/Container') ||
|
||||
importPath === '@/ui/Box' ||
|
||||
importPath === '@/ui/Surface' ||
|
||||
importPath === '@/ui/Layout' ||
|
||||
importPath === '@/ui/Container';
|
||||
|
||||
if (isPrimitiveImport) {
|
||||
node.specifiers.forEach(specifier => {
|
||||
let importedName = '';
|
||||
|
||||
if (specifier.type === 'ImportSpecifier') {
|
||||
importedName = specifier.imported.name;
|
||||
} else if (specifier.type === 'ImportDefaultSpecifier') {
|
||||
importedName = specifier.local.name;
|
||||
}
|
||||
|
||||
context.report({
|
||||
node: specifier,
|
||||
messageId: 'noGenericPrimitive',
|
||||
data: { name: importedName },
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
JSXAttribute(node) {
|
||||
if (!isComponent) return;
|
||||
|
||||
if (node.name.name === 'className') {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'noClassName',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
ExportNamedDeclaration(node) {
|
||||
if (!isUiLayer) return;
|
||||
if (!node.source) return;
|
||||
|
||||
const exportPath = node.source.value;
|
||||
if (exportPath.includes('/primitives/') || exportPath.startsWith('./primitives/')) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'noPrimitiveExport',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
ExportAllDeclaration(node) {
|
||||
if (!isUiLayer) return;
|
||||
|
||||
const exportPath = node.source.value;
|
||||
if (exportPath.includes('/primitives/') || exportPath.startsWith('./primitives/')) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'noPrimitiveExport',
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user