From 01468ab5c81e429174e7a3daf238f65c8ad9764c Mon Sep 17 00:00:00 2001 From: adilallo <39313955+adilallo@users.noreply.github.com> Date: Wed, 28 Jan 2026 11:52:42 -0700 Subject: [PATCH] Add ESLint back into CI pipeline --- .gitea/workflows/ci.yaml | 27 +++++---- app/components/Input.tsx | 13 ++--- app/components/NumberedCard.tsx | 34 ++++++------ app/components/RelatedArticles.tsx | 2 +- app/components/TextArea.tsx | 13 ++--- app/hooks/index.ts | 9 ++- app/hooks/useComponentStyles.ts | 4 +- app/hooks/useFormValidation.ts | 55 +++++++++++-------- app/hooks/useSchemaData.ts | 11 +++- docs/CUSTOM_HOOKS.md | 38 +++++++++---- docs/README.md | 6 ++ lib/logger.ts | 1 - .../page-flow.integration.test.jsx | 4 +- tests/performance/performance-monitor.js | 24 +++++--- tests/unit/BlogPage.test.jsx | 2 +- tests/unit/Page.test.jsx | 16 ++++-- tests/unit/hooks/useClickOutside.test.jsx | 12 +++- vitest.setup.ts | 17 +++--- 18 files changed, 171 insertions(+), 117 deletions(-) diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 3a5f2ce..235e3bf 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -491,20 +491,19 @@ jobs: # - run: npm run test:sb # env: { CI: true } - # Temporarily disabled - 523 pre-existing ESLint issues will be addressed in separate ticket - # lint: - # runs-on: [self-hosted, macos-latest] - # steps: - # - uses: actions/checkout@v4 - # - uses: actions/setup-node@v4 - # if: ${{ github.server_url == 'https://github.com' }} - # with: { node-version: 20, cache: npm } - # - uses: actions/setup-node@v4 - # if: ${{ github.server_url != 'https://github.com' || !github.server_url }} - # with: { node-version: 20 } - # - run: npm ci - # - run: npm run lint - # - run: npm exec prettier -- --check "**/*.{js,jsx,ts,tsx,json,css,md}" + lint: + runs-on: [self-hosted, macos-latest] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + if: ${{ github.server_url == 'https://github.com' }} + with: { node-version: 20, cache: npm } + - uses: actions/setup-node@v4 + if: ${{ github.server_url != 'https://github.com' || !github.server_url }} + with: { node-version: 20 } + - run: npm ci + - run: npm run lint + - run: npm exec prettier -- --check "**/*.{js,jsx,ts,tsx,json,css,md}" build: runs-on: [self-hosted, macos-latest] diff --git a/app/components/Input.tsx b/app/components/Input.tsx index 121e9f8..823cc60 100644 --- a/app/components/Input.tsx +++ b/app/components/Input.tsx @@ -151,13 +151,12 @@ const Input = forwardRef( `.trim(); // Form field handlers with disabled state handling - const { handleChange, handleFocus, handleBlur } = useFormField< - HTMLInputElement - >(disabled, { - onChange, - onFocus, - onBlur, - }); + const { handleChange, handleFocus, handleBlur } = + useFormField(disabled, { + onChange, + onFocus, + onBlur, + }); return (
diff --git a/app/components/NumberedCard.tsx b/app/components/NumberedCard.tsx index f3d836e..317fca2 100644 --- a/app/components/NumberedCard.tsx +++ b/app/components/NumberedCard.tsx @@ -10,25 +10,23 @@ interface NumberedCardProps { iconColor?: string; } -const NumberedCard = memo( - ({ number, text }) => { - return ( -
- {/* Section Number - Top right (lg breakpoint) */} -
- -
- - {/* Card Content - Bottom left (lg breakpoint) */} -
-

- {text} -

-
+const NumberedCard = memo(({ number, text }) => { + return ( +
+ {/* Section Number - Top right (lg breakpoint) */} +
+
- ); - }, -); + + {/* Card Content - Bottom left (lg breakpoint) */} +
+

+ {text} +

+
+
+ ); +}); NumberedCard.displayName = "NumberedCard"; diff --git a/app/components/RelatedArticles.tsx b/app/components/RelatedArticles.tsx index 300e36f..791b47f 100644 --- a/app/components/RelatedArticles.tsx +++ b/app/components/RelatedArticles.tsx @@ -108,7 +108,7 @@ const RelatedArticles = memo( } return ( -
diff --git a/app/components/TextArea.tsx b/app/components/TextArea.tsx index af75439..6511658 100644 --- a/app/components/TextArea.tsx +++ b/app/components/TextArea.tsx @@ -155,13 +155,12 @@ const TextArea = forwardRef( `.trim(); // Form field handlers with disabled state handling - const { handleChange, handleFocus, handleBlur } = useFormField< - HTMLTextAreaElement - >(disabled, { - onChange, - onFocus, - onBlur, - }); + const { handleChange, handleFocus, handleBlur } = + useFormField(disabled, { + onChange, + onFocus, + onBlur, + }); return (
diff --git a/app/hooks/index.ts b/app/hooks/index.ts index 8cf1fea..188245c 100644 --- a/app/hooks/index.ts +++ b/app/hooks/index.ts @@ -1,6 +1,6 @@ /** * Custom hooks for reusable component logic - * + * * This module exports all custom hooks used throughout the application. * Hooks encapsulate complex logic and state management that can be reused * across multiple components. @@ -12,7 +12,12 @@ export { useComponentId } from "./useComponentId"; export { useFormField } from "./useFormField"; export { useComponentStyles } from "./useComponentStyles"; export { useSchemaData } from "./useSchemaData"; -export { useMediaQuery, useIsMobile, useIsDesktop, BREAKPOINTS } from "./useMediaQuery"; +export { + useMediaQuery, + useIsMobile, + useIsDesktop, + BREAKPOINTS, +} from "./useMediaQuery"; export { useFormValidation, validationRules } from "./useFormValidation"; export type { SizeStyleConfig, diff --git a/app/hooks/useComponentStyles.ts b/app/hooks/useComponentStyles.ts index 477c3ed..a4aa882 100644 --- a/app/hooks/useComponentStyles.ts +++ b/app/hooks/useComponentStyles.ts @@ -61,9 +61,7 @@ export interface UseComponentStylesOptions { * }); * ``` */ -export function useComponentStyles( - options: UseComponentStylesOptions, -): { +export function useComponentStyles(options: UseComponentStylesOptions): { sizeClasses: Record; stateClasses: Record; } { diff --git a/app/hooks/useFormValidation.ts b/app/hooks/useFormValidation.ts index 8325ec7..a46abab 100644 --- a/app/hooks/useFormValidation.ts +++ b/app/hooks/useFormValidation.ts @@ -22,24 +22,30 @@ export const validationRules = { return emailRegex.test(value) ? null : "Please enter a valid email address"; }, - minLength: (min: number) => (value: string): string | null => { - if (!value) return null; - return value.length >= min - ? null - : `Must be at least ${min} characters long`; - }, + minLength: + (min: number) => + (value: string): string | null => { + if (!value) return null; + return value.length >= min + ? null + : `Must be at least ${min} characters long`; + }, - maxLength: (max: number) => (value: string): string | null => { - if (!value) return null; - return value.length <= max - ? null - : `Must be no more than ${max} characters long`; - }, + maxLength: + (max: number) => + (value: string): string | null => { + if (!value) return null; + return value.length <= max + ? null + : `Must be no more than ${max} characters long`; + }, - pattern: (regex: RegExp, message: string) => (value: string): string | null => { - if (!value) return null; - return regex.test(value) ? null : message; - }, + pattern: + (regex: RegExp, message: string) => + (value: string): string | null => { + if (!value) return null; + return regex.test(value) ? null : message; + }, }; /** @@ -182,13 +188,16 @@ export function useFormValidation(options: UseFormValidationOptions) { }, [initialValues]); // Set field value programmatically - const setValue = useCallback((name: string, value: string) => { - setValues((prev) => ({ ...prev, [name]: value })); - if (validateOnChange) { - const error = validateField(name, value); - setErrors((prev) => ({ ...prev, [name]: error })); - } - }, [validateOnChange, validateField]); + const setValue = useCallback( + (name: string, value: string) => { + setValues((prev) => ({ ...prev, [name]: value })); + if (validateOnChange) { + const error = validateField(name, value); + setErrors((prev) => ({ ...prev, [name]: error })); + } + }, + [validateOnChange, validateField], + ); return { values, diff --git a/app/hooks/useSchemaData.ts b/app/hooks/useSchemaData.ts index 592bbcd..3eb1622 100644 --- a/app/hooks/useSchemaData.ts +++ b/app/hooks/useSchemaData.ts @@ -144,7 +144,12 @@ export function useSchemaData( type: "BreadcrumbList"; items: Array<{ name: string; url: string }>; }, -): SchemaOrganization | SchemaWebSite | SchemaHowTo | SchemaArticle | SchemaBreadcrumbList { +): + | SchemaOrganization + | SchemaWebSite + | SchemaHowTo + | SchemaArticle + | SchemaBreadcrumbList { return useMemo(() => { switch (config.type) { case "Organization": @@ -216,7 +221,9 @@ export function useSchemaData( "@id": config.mainEntityOfPage, }, }), - ...(config.articleSection && { articleSection: config.articleSection }), + ...(config.articleSection && { + articleSection: config.articleSection, + }), ...(config.keywords && { keywords: config.keywords }), } as SchemaArticle; diff --git a/docs/CUSTOM_HOOKS.md b/docs/CUSTOM_HOOKS.md index 73a62d5..facb73f 100644 --- a/docs/CUSTOM_HOOKS.md +++ b/docs/CUSTOM_HOOKS.md @@ -15,6 +15,7 @@ Detects clicks outside of specified elements. Useful for closing dropdowns, moda **Location:** `app/hooks/useClickOutside.ts` **Usage:** + ```tsx import { useClickOutside } from "../hooks"; @@ -26,6 +27,7 @@ useClickOutside([menuRef, buttonRef], () => setIsOpen(false), isOpen); ``` **Parameters:** + - `refs`: Array of refs to elements that should not trigger the callback - `handler`: Callback function to execute when clicking outside - `enabled`: Whether the hook is enabled (default: true) @@ -41,6 +43,7 @@ Centralized analytics tracking for component interactions. Supports both Google **Location:** `app/hooks/useAnalytics.ts` **Usage:** + ```tsx import { useAnalytics } from "../hooks"; @@ -66,6 +69,7 @@ trackCustomEvent( ``` **Returns:** + - `trackEvent`: Function to track standard analytics events - `trackCustomEvent`: Function to track custom events with optional callback @@ -80,6 +84,7 @@ Generates unique component IDs for accessibility. Provides consistent ID generat **Location:** `app/hooks/useComponentId.ts` **Usage:** + ```tsx import { useComponentId } from "../hooks"; @@ -89,10 +94,12 @@ const { id, labelId } = useComponentId("input", props.id); ``` **Parameters:** + - `prefix`: Prefix for the generated ID (e.g., "input", "select") - `providedId`: Optional ID provided via props (takes precedence) **Returns:** + - `id`: Component ID - `labelId`: Associated label ID for accessibility @@ -107,6 +114,7 @@ Manages form field event handlers with disabled state handling. Ensures handlers **Location:** `app/hooks/useFormField.ts` **Usage:** + ```tsx import { useFormField } from "../hooks"; @@ -117,18 +125,16 @@ const { handleChange, handleFocus, handleBlur } = useFormField(disabled, { }); // Use in component - +; ``` **Parameters:** + - `disabled`: Whether the field is disabled - `handlers`: Object containing onChange, onFocus, onBlur handlers **Returns:** + - `handleChange`: Wrapped onChange handler - `handleFocus`: Wrapped onFocus handler - `handleBlur`: Wrapped onBlur handler @@ -144,6 +150,7 @@ Manages component size and state styles. Provides a consistent pattern for styli **Location:** `app/hooks/useComponentStyles.ts` **Usage:** + ```tsx import { useComponentStyles } from "../hooks"; @@ -178,6 +185,7 @@ Generates Schema.org structured data (JSON-LD) for SEO and search engines. **Location:** `app/hooks/useSchemaData.ts` **Usage:** + ```tsx import { useSchemaData } from "../hooks"; @@ -205,10 +213,11 @@ const orgSchema = useSchemaData({