website refactor
This commit is contained in:
82
apps/website/eslint-rules/component-classification.js
Normal file
82
apps/website/eslint-rules/component-classification.js
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* ESLint rule to suggest proper component classification
|
||||
*
|
||||
* Architecture:
|
||||
* - app/ - Pages and layouts only (no business logic)
|
||||
* - components/ - App-level components (can be stateful, can use hooks)
|
||||
* - ui/ - Pure, reusable UI elements (stateless, no hooks)
|
||||
* - hooks/ - Shared stateful logic
|
||||
*
|
||||
* This rule provides SUGGESTIONS, not errors, for component placement.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'suggestion',
|
||||
docs: {
|
||||
description: 'Suggest proper component classification',
|
||||
category: 'Architecture',
|
||||
recommended: false,
|
||||
},
|
||||
fixable: 'code',
|
||||
schema: [],
|
||||
messages: {
|
||||
uiShouldBePure: 'This appears to be a pure UI element. Consider moving to ui/ for maximum reusability.',
|
||||
componentShouldBeInComponents: 'This component uses state/hooks. Consider moving to components/.',
|
||||
pureComponentInComponents: 'Pure component in components/. Consider moving to ui/ for better reusability.',
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const filename = context.getFilename();
|
||||
const isInUi = filename.includes('/ui/');
|
||||
const isInComponents = filename.includes('/components/');
|
||||
const isInApp = filename.includes('/app/');
|
||||
|
||||
if (!isInUi && !isInComponents) return {};
|
||||
|
||||
return {
|
||||
Program(node) {
|
||||
const sourceCode = context.getSourceCode();
|
||||
const text = sourceCode.getText();
|
||||
|
||||
// Detect stateful patterns
|
||||
const hasState = /useState|useReducer|this\.state/.test(text);
|
||||
const hasEffects = /useEffect|useLayoutEffect/.test(text);
|
||||
const hasContext = /useContext/.test(text);
|
||||
const hasComplexLogic = /if\s*\(|switch\s*\(|for\s*\(|while\s*\(/.test(text);
|
||||
|
||||
// Detect pure UI patterns (just JSX, props, simple functions)
|
||||
const hasOnlyJsx = /^\s*import.*from.*;\s*export\s+function\s+\w+\s*\([^)]*\)\s*{?\s*return\s*\(?.*\)?;?\s*}?\s*$/m.test(text);
|
||||
const hasNoLogic = !hasState && !hasEffects && !hasContext && !hasComplexLogic;
|
||||
|
||||
if (isInUi && hasState) {
|
||||
context.report({
|
||||
loc: { line: 1, column: 0 },
|
||||
messageId: 'componentShouldBeInComponents',
|
||||
});
|
||||
}
|
||||
|
||||
if (isInComponents && hasNoLogic && hasOnlyJsx) {
|
||||
context.report({
|
||||
loc: { line: 1, column: 0 },
|
||||
messageId: 'pureComponentInComponents',
|
||||
});
|
||||
}
|
||||
|
||||
if (isInComponents && !hasState && !hasEffects && !hasContext) {
|
||||
// Check if it's mostly just rendering props
|
||||
const hasManyProps = /\{\s*\.\.\.props\s*\}/.test(text) ||
|
||||
/\{\s*props\./.test(text);
|
||||
|
||||
if (hasManyProps && hasNoLogic) {
|
||||
context.report({
|
||||
loc: { line: 1, column: 0 },
|
||||
messageId: 'uiShouldBePure',
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user