Skip to content

Commit

Permalink
ref : add custom eslint rules for page/layout.tsx files
Browse files Browse the repository at this point in the history
  • Loading branch information
Juknum committed Aug 22, 2024
1 parent f1e08d7 commit 0fae631
Show file tree
Hide file tree
Showing 25 changed files with 230 additions and 120 deletions.
59 changes: 59 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
'use strict';

module.exports = {
extends: 'next/core-web-vitals',
plugins: [
'unused-imports',
'custom-rules',
],
rules: {
'comma-dangle': ['error', 'always-multiline'],
'object-curly-spacing': ['warn', 'always'],
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
'import/order': [
'error',
{
'newlines-between': 'always',
groups: [
'builtin',
'external',
'internal',
['parent', 'sibling', 'index'],
'type',
],
pathGroups: [
{
pattern: 'react',
group: 'builtin',
position: 'after',
},
{
pattern: 'react-icons/**',
group: 'builtin',
position: 'after',
},
{
pattern: 'next/**',
group: 'builtin',
position: 'before',
},
],
pathGroupsExcludedImportTypes: ['react', 'react-icons/**', 'next/**'],
alphabetize: {
order: 'asc',
caseInsensitive: false,
},
},
],
indent: ['error', 'tab', { SwitchCase: 1 }],
'no-multi-spaces': ['error', { ignoreEOLComments: true }],
'no-multiple-empty-lines': ['error', { max: 1, maxEOF: 1 }],
quotes: ['error', 'single'],
semi: ['error', 'always'],
'unused-imports/no-unused-imports': 'error',

'custom-rules/page-export-naming': 'error',
'custom-rules/layout-export-naming': 'error',
},
};

46 changes: 0 additions & 46 deletions .eslintrc.json

This file was deleted.

8 changes: 8 additions & 0 deletions eslint-plugins/eslint-plugin-custom-rules.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const plugin = {
rules: {
'page-export-naming': require('./rules/page-export-naming.cjs'),
'layout-export-naming': require('./rules/layout-export-naming.cjs'),
},
};

module.exports = plugin;
12 changes: 12 additions & 0 deletions eslint-plugins/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "eslint-plugin-custom-rules",
"type":"module",
"version": "1.0.0",
"main": "eslint-plugin-custom-rules.cjs",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"description": ""
}
57 changes: 57 additions & 0 deletions eslint-plugins/rules/layout-export-naming.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const { sep } = require('path');

module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Enforce the default export names to ends with "Layout" in layout.tsx files',
category: 'Best Practices',
recommended: true,
},
messages: {
invalidExportName: 'Default export name must ends with "Layout"',
invalidExportType: 'Default export must be a function',
},
fixable: 'code',
schema: [],
},
/**
* @param {import('eslint').Rule.RuleContext} context
*/
create(context) {
const filename = context.filename.split(sep).pop();
if (filename !== 'layout.tsx') return {};

return {
ExportDefaultDeclaration(node) {
if (node.declaration.type === 'FunctionDeclaration' || (node.declaration.type === 'ArrowFunctionExpression' && node.declaration.id)) {
/**
* @type {string | undefined}
*/
const functionName = node.declaration.id && node.declaration.id.name;

if (functionName && !functionName.endsWith('Layout')) {
context.report({
node,
messageId: 'invalidExportName',
fix(fixed) {
const newName = `${functionName}Layout`;
const start = node.declaration.id.range[0];
const end = node.declaration.id.range[1];
return fixed.replaceTextRange([start, end], newName);
},
});
}
}

if (node.declaration.type === 'Identifier') {
context.report({
node,
messageId: 'invalidExportType',
});
}
},
};

},
};
57 changes: 57 additions & 0 deletions eslint-plugins/rules/page-export-naming.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const { sep } = require('path');

module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Enforce the default export names to ends with "Page" in .tsx files',
category: 'Best Practices',
recommended: true,
},
messages: {
invalidExportName: 'Default export name must ends with "Page"',
invalidExportType: 'Default export must be a function',
},
fixable: 'code',
schema: [],
},
/**
* @param {import('eslint').Rule.RuleContext} context
*/
create(context) {
const filename = context.filename.split(sep).pop();
if (filename !== 'page.tsx') return {};

return {
ExportDefaultDeclaration(node) {
if (node.declaration.type === 'FunctionDeclaration' || (node.declaration.type === 'ArrowFunctionExpression' && node.declaration.id)) {
/**
* @type {string | undefined}
*/
const functionName = node.declaration.id && node.declaration.id.name;

if (functionName && !functionName.endsWith('Page')) {
context.report({
node,
messageId: 'invalidExportName',
fix(fixed) {
const newName = `${functionName}Page`;
const start = node.declaration.id.range[0];
const end = node.declaration.id.range[1];
return fixed.replaceTextRange([start, end], newName);
},
});
}
}

if (node.declaration.type === 'Identifier') {
context.report({
node,
messageId: 'invalidExportType',
});
}
},
};

},
};
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"cross-env": "^7.0.3",
"eslint": "^8.57.0",
"eslint-config-next": "^14.2.5",
"eslint-plugin-custom-rules": "file:eslint-plugins",
"eslint-plugin-unused-imports": "^4.1.3",
"postcss": "^8.4.39",
"postcss-preset-mantine": "^1.17.0",
Expand Down
4 changes: 2 additions & 2 deletions src/app/(pages)/(protected)/contribute/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import { ActionIcon, Badge, Button, FloatingIndicator, Group, Indicator, Kbd, Li
import { useHotkeys, useOs, usePrevious, useViewportSize } from '@mantine/hooks';
import { Resolution, Status } from '@prisma/client';

import ForkInfo from '~/components/fork';
import { SmallTile } from '~/components/base/small-tile';
import { TextureImage } from '~/components/textures/texture-img';
import { Tile } from '~/components/base/tile';
import ForkInfo from '~/components/fork';
import { TextureImage } from '~/components/textures/texture-img';
import { useCurrentUser } from '~/hooks/use-current-user';
import { useEffectOnce } from '~/hooks/use-effect-once';
import { BREAKPOINT_MOBILE_LARGE, COLORS, gitBlobUrl, gitCommitUrl, GRADIENT, GRADIENT_DANGER } from '~/lib/constants';
Expand Down
4 changes: 1 addition & 3 deletions src/app/(pages)/(protected)/council/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface ProtectedLayoutProps {
children: React.ReactNode;
};

const CouncilPage = ({ children }: ProtectedLayoutProps) => {
export default function CouncilLayout({ children }: ProtectedLayoutProps) {
const tabs = [
{ value: 'submissions', label: 'Submissions' },
{ value: 'modpacks', label: 'Modpacks' },
Expand All @@ -28,5 +28,3 @@ const CouncilPage = ({ children }: ProtectedLayoutProps) => {
</RoleGate>
);
};

export default CouncilPage;
6 changes: 2 additions & 4 deletions src/app/(pages)/(protected)/council/modpacks/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { Badge, Group, Text, TextInput, Button, Select, Pagination, Stack } from
import { useDisclosure, usePrevious } from '@mantine/hooks';
import { UserRole } from '@prisma/client';

import { DashboardItem } from '~/components/dashboard-item/dashboard-item';
import { Modal } from '~/components/base/modal';
import { DashboardItem } from '~/components/dashboard-item/dashboard-item';
import { useCurrentUser } from '~/hooks/use-current-user';
import { useEffectOnce } from '~/hooks/use-effect-once';
import { GRADIENT, GRADIENT_DANGER, ITEMS_PER_PAGE, ITEMS_PER_PAGE_DEFAULT } from '~/lib/constants';
Expand All @@ -18,7 +18,7 @@ import { ModpackModal } from './modal/modpack-modal';

import type { Modpack } from '@prisma/client';

const ModpacksPanel = () => {
export default function ModpacksPage() {
const user = useCurrentUser()!;
const itemsPerPage = useMemo(() => ITEMS_PER_PAGE, []);

Expand Down Expand Up @@ -212,5 +212,3 @@ const ModpacksPanel = () => {
</>
);
};

export default ModpacksPanel;
6 changes: 2 additions & 4 deletions src/app/(pages)/(protected)/council/mods/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { Badge, Button, Group, Pagination, Select, Stack, Switch, Text, TextInpu
import { useDisclosure, usePrevious, useViewportSize } from '@mantine/hooks';
import { UserRole } from '@prisma/client';

import { DashboardItem } from '~/components/dashboard-item/dashboard-item';
import { Modal } from '~/components/base/modal';
import { DashboardItem } from '~/components/dashboard-item/dashboard-item';
import { ModUpload } from '~/components/mods-upload';
import { useCurrentUser } from '~/hooks/use-current-user';
import { useEffectOnce } from '~/hooks/use-effect-once';
Expand All @@ -21,7 +21,7 @@ import type { Mod } from '@prisma/client';

type ModWVer = Mod & { unknownVersion: boolean };

const ModsPanel = () => {
export default function ModsPage() {
const user = useCurrentUser()!;
const { width } = useViewportSize();

Expand Down Expand Up @@ -236,5 +236,3 @@ const ModsPanel = () => {
</>
);
};

export default ModsPanel;
3 changes: 1 addition & 2 deletions src/app/(pages)/(protected)/council/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

import { redirect } from 'next/navigation';

const CouncilPage = () => {
export default function CouncilPage() {
redirect('/council/submissions');
};

export default CouncilPage;
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { Button, Group, Stack, Text, Tooltip } from '@mantine/core';
import { useViewportSize } from '@mantine/hooks';
import { ReactCompareSlider } from 'react-compare-slider';

import { TextureImage } from '~/components/textures/texture-img';
import { Tile } from '~/components/base/tile';
import { TextureImage } from '~/components/textures/texture-img';
import { useCurrentUser } from '~/hooks/use-current-user';
import { BREAKPOINT_DESKTOP_MEDIUM, BREAKPOINT_MOBILE_LARGE, BREAKPOINT_TABLET } from '~/lib/constants';
import { checkContributionStatus } from '~/server/data/contributions';
Expand Down
4 changes: 1 addition & 3 deletions src/app/(pages)/(protected)/council/submissions/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import type { Texture } from '@prisma/client';
import type { GetPendingContributions } from '~/server/data/contributions';
import type { PublicUser } from '~/types';

const CouncilContributionsPanel = () => {
export default function CouncilSubmissionsPage() {
const [textures, setTextures] = useState<Texture[]>([]);

const [isLightBackground, setLightBackground] = useState(false);
Expand Down Expand Up @@ -191,5 +191,3 @@ const CouncilContributionsPanel = () => {
</Stack>
);
};

export default CouncilContributionsPanel;
Loading

0 comments on commit 0fae631

Please sign in to comment.