From 882f2104ccd3ab4adb2443ac795452a43488eb79 Mon Sep 17 00:00:00 2001 From: Andriy Lysnevych Date: Mon, 18 Nov 2024 01:49:41 +0200 Subject: [PATCH] Add eslint-react plugin --- demo/eslint.config.js | 33 +- eslint.common.react.config.js | 38 ++ package.json | 1 + packages/p2p-media-loader-demo/dummy.ts | 0 .../p2p-media-loader-demo/eslint.config.js | 33 +- .../src/components/P2PVideoDemo.tsx | 7 +- .../src/components/PlaybackOptions.tsx | 95 ++--- .../src/components/chart/ChartLegend.tsx | 1 + .../components/chart/DownloadStatsChart.tsx | 4 +- .../components/debugTools/DebugSelector.tsx | 2 +- .../src/components/players/hlsjs/Hlsjs.tsx | 12 +- .../players/hlsjs/HlsjsClapprPlayer.tsx | 10 +- .../components/players/hlsjs/HlsjsDPLayer.tsx | 11 +- .../players/hlsjs/HlsjsOpenPlayer.tsx | 12 +- .../components/players/hlsjs/HlsjsPlyr.tsx | 12 +- .../src/components/players/shaka/Shaka.tsx | 10 +- .../components/players/shaka/ShakaClappr.tsx | 11 +- .../components/players/shaka/ShakaDPlayer.tsx | 11 +- .../components/players/shaka/ShakaPlyr.tsx | 12 +- .../p2p-media-loader-demo/tsconfig.node.json | 2 +- pnpm-lock.yaml | 369 ++++++++++++++++++ 21 files changed, 500 insertions(+), 186 deletions(-) create mode 100644 eslint.common.react.config.js create mode 100644 packages/p2p-media-loader-demo/dummy.ts diff --git a/demo/eslint.config.js b/demo/eslint.config.js index 43ad213e..daa74fc0 100644 --- a/demo/eslint.config.js +++ b/demo/eslint.config.js @@ -1,35 +1,6 @@ // @ts-check -import { CommonConfig } from "../eslint.common.config.js"; import tsEslint from "typescript-eslint"; -import reactRefresh from "eslint-plugin-react-refresh"; -import reactHooks from "eslint-plugin-react-hooks"; -import reactPlugin from "eslint-plugin-react"; +import { CommonReactConfig } from "../eslint.common.react.config.js"; -export default tsEslint.config( - ...CommonConfig, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - reactPlugin.configs.flat?.recommended, // This is not a plugin object, but a shareable config object - reactPlugin.configs.flat?.["jsx-runtime"], // Add this if you are using React 17+ - { - plugins: { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - "react-hooks": reactHooks, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - "react-refresh": reactRefresh, - }, - rules: { - .../** @type {Record} */ ( - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - reactHooks.configs.recommended.rules - ), - "import/extensions": "off", - }, - settings: { - react: { - version: "detect", - }, - }, - }, -); +export default tsEslint.config(...CommonReactConfig); diff --git a/eslint.common.react.config.js b/eslint.common.react.config.js new file mode 100644 index 00000000..f279fea8 --- /dev/null +++ b/eslint.common.react.config.js @@ -0,0 +1,38 @@ +// @ts-check + +import { CommonConfig } from "./eslint.common.config.js"; +import reactRefresh from "eslint-plugin-react-refresh"; +import reactHooks from "eslint-plugin-react-hooks"; +import reactPlugin from "eslint-plugin-react"; +import react from "@eslint-react/eslint-plugin"; + +export const CommonReactConfig = /** @type {typeof CommonConfig} */ ([ + ...CommonConfig, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + reactPlugin.configs.flat?.recommended, // This is not a plugin object, but a shareable config object + reactPlugin.configs.flat?.["jsx-runtime"], // Add this if you are using React 17+ + react.configs.all, + { + plugins: { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + "react-hooks": reactHooks, + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + "react-refresh": reactRefresh, + }, + rules: { + .../** @type {Record} */ ( + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + reactHooks.configs.recommended.rules + ), + "import/extensions": "off", + "@eslint-react/avoid-shorthand-fragment": "off", + "@eslint-react/avoid-shorthand-boolean": "off", + "@eslint-react/naming-convention/filename": "off", + }, + settings: { + react: { + version: "detect", + }, + }, + }, +]); diff --git a/package.json b/package.json index 0e48067d..0c172b49 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "create-doc": "pnpm typedoc" }, "devDependencies": { + "@eslint-react/eslint-plugin": "^1.16.1", "@types/eslint__js": "^8.42.3", "eslint": "^9.14.0", "eslint-plugin-import": "^2.31.0", diff --git a/packages/p2p-media-loader-demo/dummy.ts b/packages/p2p-media-loader-demo/dummy.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/p2p-media-loader-demo/eslint.config.js b/packages/p2p-media-loader-demo/eslint.config.js index 739db964..c434d746 100644 --- a/packages/p2p-media-loader-demo/eslint.config.js +++ b/packages/p2p-media-loader-demo/eslint.config.js @@ -1,35 +1,6 @@ // @ts-check -import { CommonConfig } from "../../eslint.common.config.js"; import tsEslint from "typescript-eslint"; -import reactRefresh from "eslint-plugin-react-refresh"; -import reactHooks from "eslint-plugin-react-hooks"; -import reactPlugin from "eslint-plugin-react"; +import { CommonReactConfig } from "../../eslint.common.react.config.js"; -export default tsEslint.config( - ...CommonConfig, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - reactPlugin.configs.flat?.recommended, // This is not a plugin object, but a shareable config object - reactPlugin.configs.flat?.["jsx-runtime"], // Add this if you are using React 17+ - { - plugins: { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - "react-hooks": reactHooks, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - "react-refresh": reactRefresh, - }, - rules: { - .../** @type {Record} */ ( - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - reactHooks.configs.recommended.rules - ), - "import/extensions": "off", - }, - settings: { - react: { - version: "detect", - }, - }, - }, -); +export default tsEslint.config(...CommonReactConfig); diff --git a/packages/p2p-media-loader-demo/src/components/P2PVideoDemo.tsx b/packages/p2p-media-loader-demo/src/components/P2PVideoDemo.tsx index b80506c6..97d2a6e7 100644 --- a/packages/p2p-media-loader-demo/src/components/P2PVideoDemo.tsx +++ b/packages/p2p-media-loader-demo/src/components/P2PVideoDemo.tsx @@ -134,6 +134,9 @@ export const P2PVideoDemo = ({ ) : null; }; + const isDebugToolsEnabled = + debugToolsEnabled || queryParams.debug === DEBUG_COMPONENT_ENABLED; + return ( <>
@@ -165,9 +168,7 @@ export const P2PVideoDemo = ({ )}
- {(debugToolsEnabled || queryParams.debug === DEBUG_COMPONENT_ENABLED) && ( - - )} + {isDebugToolsEnabled && } ); }; diff --git a/packages/p2p-media-loader-demo/src/components/PlaybackOptions.tsx b/packages/p2p-media-loader-demo/src/components/PlaybackOptions.tsx index 0f825307..2e2faed3 100644 --- a/packages/p2p-media-loader-demo/src/components/PlaybackOptions.tsx +++ b/packages/p2p-media-loader-demo/src/components/PlaybackOptions.tsx @@ -39,60 +39,61 @@ export const PlaybackOptions = ({ }; return ( - <> -
-
- - -
+
+
+ + +
-
- - + + {Object.entries(hlsPlayers).map(([key, name]) => ( + + ))} + + {Object.keys(shakaPlayers).length > 0 && ( + + {Object.entries(shakaPlayers).map(([key, name]) => ( ))} - {Object.keys(shakaPlayers).length > 0 && ( - - {Object.entries(shakaPlayers).map(([key, name]) => ( - - ))} - - )} - -
+ )} + +
-
- - -
+
+ +
- +
); }; diff --git a/packages/p2p-media-loader-demo/src/components/chart/ChartLegend.tsx b/packages/p2p-media-loader-demo/src/components/chart/ChartLegend.tsx index 3fc0a5bd..9c03ba60 100644 --- a/packages/p2p-media-loader-demo/src/components/chart/ChartLegend.tsx +++ b/packages/p2p-media-loader-demo/src/components/chart/ChartLegend.tsx @@ -13,6 +13,7 @@ export const ChartLegend = ({ legendItems }: ChartLegendProps) => { return (
{legendItems.map((item, index) => ( + // eslint-disable-next-line @eslint-react/no-array-index-key

{item.content}

diff --git a/packages/p2p-media-loader-demo/src/components/chart/DownloadStatsChart.tsx b/packages/p2p-media-loader-demo/src/components/chart/DownloadStatsChart.tsx index 6a25658f..52c2a2c7 100644 --- a/packages/p2p-media-loader-demo/src/components/chart/DownloadStatsChart.tsx +++ b/packages/p2p-media-loader-demo/src/components/chart/DownloadStatsChart.tsx @@ -34,7 +34,9 @@ type StoredData = { } & DownloadStats; export const DownloadStatsChart = ({ downloadStatsRef }: StatsChartProps) => { - const [data, setData] = useState(generateInitialStackedData()); + const [data, setData] = useState(() => + generateInitialStackedData(), + ); const [storedData, setStoredData] = useState({ totalDownloaded: 0, diff --git a/packages/p2p-media-loader-demo/src/components/debugTools/DebugSelector.tsx b/packages/p2p-media-loader-demo/src/components/debugTools/DebugSelector.tsx index 02b31280..969592ae 100644 --- a/packages/p2p-media-loader-demo/src/components/debugTools/DebugSelector.tsx +++ b/packages/p2p-media-loader-demo/src/components/debugTools/DebugSelector.tsx @@ -41,7 +41,7 @@ function useLocalStorageItem( storageItemToValue: (storageItem: string | null) => T, ): [T, React.Dispatch>] { const [value, setValue] = useState( - storageItemToValue(localStorage[prop] as string | null) ?? initValue, + () => storageItemToValue(localStorage[prop] as string | null) ?? initValue, ); const setValueExternal = useCallback( (value: T | ((prev: T) => T)) => { diff --git a/packages/p2p-media-loader-demo/src/components/players/hlsjs/Hlsjs.tsx b/packages/p2p-media-loader-demo/src/components/players/hlsjs/Hlsjs.tsx index edf13e0f..65cc6f49 100644 --- a/packages/p2p-media-loader-demo/src/components/players/hlsjs/Hlsjs.tsx +++ b/packages/p2p-media-loader-demo/src/components/players/hlsjs/Hlsjs.tsx @@ -1,5 +1,5 @@ import "./hlsjs.css"; -import { useEffect, useRef, useState } from "react"; +import { useEffect, useRef } from "react"; import { PlayerProps } from "../../../types"; import { subscribeToUiEvents } from "../utils"; import { HlsJsP2PEngine } from "p2p-media-loader-hlsjs"; @@ -14,17 +14,11 @@ export const HlsjsPlayer = ({ onChunkDownloaded, onChunkUploaded, }: PlayerProps) => { - const [isHlsSupported, setIsHlsSupported] = useState(true); - const videoRef = useRef(null); const qualityRef = useRef(null); useEffect(() => { - if (!videoRef.current) return; - if (!Hls.isSupported()) { - setIsHlsSupported(false); - return; - } + if (!videoRef.current || !Hls.isSupported()) return; const HlsWithP2P = HlsJsP2PEngine.injectMixin(Hls); const hls = new HlsWithP2P({ @@ -82,7 +76,7 @@ export const HlsjsPlayer = ({ } }; - return isHlsSupported ? ( + return Hls.isSupported() ? (