diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index f76c765b..00000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -next-env.d.ts diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 1550b9cb..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,26 +0,0 @@ -module.exports = { - extends: ['@prezly/eslint-config/nextjs'], - rules: { - // TODO: NextJS Dynamic import doesn't work too well with named exports. - // Gotta figure out how to make them work together. - // Some hints here: https://github.com/vercel/next.js/issues/22278#issuecomment-1009865850 - 'import/no-default-export': 'off', - 'no-restricted-exports': 'off', - - 'jsx-a11y/label-has-associated-control': [ - 'warn', - { - assert: 'either', - controlComponents: ['Field'], - }, - ], - - // Extra rules - 'react/jsx-props-no-spreading': [ - 'error', - { - exceptions: ['FormattedMessage'], - }, - ], - }, -}; diff --git a/.github/renovate.json b/.github/renovate.json index f8ca4af6..e41b64fc 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,6 +1,3 @@ { - "extends": [ - "config:base", - "github>prezly/renovate-presets:themes-nextjs" - ] + "extends": ["config:base", "github>prezly/renovate-presets:themes-nextjs"] } diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index afcbf3f4..00000000 --- a/.prettierignore +++ /dev/null @@ -1,4 +0,0 @@ -.next/ -build/ -node_modules/ -README.md diff --git a/.prettierrc.js b/.prettierrc.js deleted file mode 100644 index 3f04ee5e..00000000 --- a/.prettierrc.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('@prezly/eslint-config/lib/prettier'); diff --git a/.stylelintrc.json b/.stylelintrc.json deleted file mode 100644 index f128edb6..00000000 --- a/.stylelintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["@prezly/eslint-config/stylelint"] -} diff --git a/README.md b/README.md index ae841421..a260d36c 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Lena Prezly Theme is based on [Next.js] 12+ framework. - Data-fetching is handled by [Prezly Theme Kit] and [Prezly SDK]. - Multi-language is powered by [React Intl] and [Prezly Themes Translations]. - Analytics powered by [Prezly Analytics]. -- Code-style is ensured by [ESLint], [StyleLint] and [Prettier]. +- Code-style is ensured by [Biome]. - Search is powered by [Algolia] - Error-logging with [Sentry]. @@ -59,7 +59,7 @@ This repo is configured with GitHub workflows to run linter checks on every push npm run check ``` -Prettier is configured to be managed by ESLint, but you can always run it separately with `npm run prettier` to check code-style, or with `npm run prettier:fix` to auto-fix code-style issues in the project. +To auto-fix code style issues in the project, run `npm run lint:fix`. ## Documentation @@ -97,10 +97,8 @@ Made with ♥ by [Prezly](https://www.prezly.com/developers) [Prezly SDK]: https://github.com/prezly/javascript-sdk [Prezly Theme Kit]: https://github.com/prezly/theme-kit-nextjs [Typescript]: https://www.typescriptlang.org -[ESLint]: https://eslint.org +[Biome]: https://biomejs.dev [Algolia]: https://algolia.com -[StyleLint]: https://stylelint.io -[Prettier]: https://prettier.io [React Intl]: https://www.npmjs.com/package/react-intl [Algolia Search]: https://www.npmjs.com/package/algoliasearch [Prezly Content React Renderer]: https://www.npmjs.com/package/@prezly/content-renderer-react-js diff --git a/biome.json b/biome.json new file mode 100644 index 00000000..10269e72 --- /dev/null +++ b/biome.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "files": { + "ignoreUnknown": true, + "ignore": [".next", "build", "node_modules", "README.md", "next-env.d.ts"] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 4, + "lineWidth": 100 + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "semicolons": "always", + "trailingCommas": "all" + } + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "a11y": { + "useKeyWithClickEvents": "off", + "useSemanticElements": "off", + "useValidAnchor": "off", + "useValidAriaRole": "off" + }, + "complexity": { + "noBannedTypes": "off", + "noForEach": "off", + "useOptionalChain": "off" + }, + "correctness": { + "useExhaustiveDependencies": "off" + }, + "security": { + "noDangerouslySetInnerHtml": "off" + }, + "style": { + "noNonNullAssertion": "off", + "useNodejsImportProtocol": "off" + }, + "suspicious": { + "noExplicitAny": "off", + "noImplicitAnyLet": "off", + "noShadowRestrictedNames": "off" + } + } + } +} diff --git a/components/CategoriesBar/CategoriesBar.tsx b/components/CategoriesBar/CategoriesBar.tsx index 00b626c1..a19ee2e1 100644 --- a/components/CategoriesBar/CategoriesBar.tsx +++ b/components/CategoriesBar/CategoriesBar.tsx @@ -27,7 +27,7 @@ function CategoriesBar() { const { paddingLeft, paddingRight } = getComputedStyle(containerRef.current); const containerWidthWithoutPadding = - containerWidth - parseInt(paddingLeft) - parseInt(paddingRight); + containerWidth - Number.parseInt(paddingLeft) - Number.parseInt(paddingRight); if (containerRef.current.scrollWidth <= containerWidthWithoutPadding) { return [categories, []]; diff --git a/components/ContentRenderer/components/Attachment/utils.ts b/components/ContentRenderer/components/Attachment/utils.ts index 938c16b6..7fdc3055 100644 --- a/components/ContentRenderer/components/Attachment/utils.ts +++ b/components/ContentRenderer/components/Attachment/utils.ts @@ -4,7 +4,7 @@ const UNITS = ['bytes', 'Kb', 'Mb', 'Gb']; // Convert byte amounts to meaningful text export function formatBytes(bytes: number | string): string { let l = 0; - let n = typeof bytes === 'number' ? bytes : parseInt(bytes, 10) || 0; + let n = typeof bytes === 'number' ? bytes : Number.parseInt(bytes, 10) || 0; while (n >= 1024) { n /= 1024; diff --git a/components/ContentRenderer/components/Gallery.tsx b/components/ContentRenderer/components/Gallery.tsx index 75809b4e..54585618 100644 --- a/components/ContentRenderer/components/Gallery.tsx +++ b/components/ContentRenderer/components/Gallery.tsx @@ -1,4 +1,4 @@ -import { DOWNLOAD, useAnalytics, VIEW } from '@prezly/analytics-nextjs'; +import { DOWNLOAD, VIEW, useAnalytics } from '@prezly/analytics-nextjs'; import { Elements } from '@prezly/content-renderer-react-js'; import type { GalleryNode } from '@prezly/story-content-format'; diff --git a/components/ContentRenderer/components/Image.tsx b/components/ContentRenderer/components/Image.tsx index 3f980578..6129ce5f 100644 --- a/components/ContentRenderer/components/Image.tsx +++ b/components/ContentRenderer/components/Image.tsx @@ -1,4 +1,4 @@ -import { DOWNLOAD, useAnalytics, VIEW } from '@prezly/analytics-nextjs'; +import { DOWNLOAD, VIEW, useAnalytics } from '@prezly/analytics-nextjs'; import { Elements } from '@prezly/content-renderer-react-js'; import type { ImageNode } from '@prezly/story-content-format'; import type { PropsWithChildren } from 'react'; diff --git a/components/NotificationsBar/LinkedText.tsx b/components/NotificationsBar/LinkedText.tsx index 356e1908..657a2140 100644 --- a/components/NotificationsBar/LinkedText.tsx +++ b/components/NotificationsBar/LinkedText.tsx @@ -1,4 +1,4 @@ -import { type ReactElement } from 'react'; +import type { ReactElement } from 'react'; interface Props { links: Link[]; diff --git a/components/NotificationsBar/NotificationsBar.tsx b/components/NotificationsBar/NotificationsBar.tsx index e9449909..d0e10117 100644 --- a/components/NotificationsBar/NotificationsBar.tsx +++ b/components/NotificationsBar/NotificationsBar.tsx @@ -3,8 +3,8 @@ import classNames from 'classnames'; import type { HTMLAttributes } from 'react'; import { useRef, useState } from 'react'; -import { useOnResize } from './lib'; import { LinkedText } from './LinkedText'; +import { useOnResize } from './lib'; import styles from './NotificationsBar.module.scss'; diff --git a/components/RichText/Html.tsx b/components/RichText/Html.tsx index a85107de..f187a7f2 100644 --- a/components/RichText/Html.tsx +++ b/components/RichText/Html.tsx @@ -1,5 +1,5 @@ import { Elements } from '@prezly/content-renderer-react-js'; -import { type HtmlNode } from '@prezly/story-content-format'; +import type { HtmlNode } from '@prezly/story-content-format'; import styles from './styles.module.scss'; diff --git a/modules/Gallery/Gallery.tsx b/modules/Gallery/Gallery.tsx index bdd1bc47..e00a365c 100644 --- a/modules/Gallery/Gallery.tsx +++ b/modules/Gallery/Gallery.tsx @@ -24,7 +24,7 @@ export default function Gallery({ gallery }: Props) { const metaDescription = useGalleryPageMetaDescription(gallery); useEffect(() => { - if (typeof window !== undefined) { + if (typeof window !== 'undefined') { setUrl(window.location.href); } }, []); diff --git a/modules/Layout/Header/CategoriesDropdown/CategoriesDropdown.tsx b/modules/Layout/Header/CategoriesDropdown/CategoriesDropdown.tsx index 050cc29e..b6fdc21c 100644 --- a/modules/Layout/Header/CategoriesDropdown/CategoriesDropdown.tsx +++ b/modules/Layout/Header/CategoriesDropdown/CategoriesDropdown.tsx @@ -39,21 +39,18 @@ function CategoriesDropdown({ return ( <> - {showAllCategoriesOnMobile && ( - <> - {filteredCategories.map((category) => ( -
  • - -
  • - ))} - - )} + {showAllCategoriesOnMobile && + filteredCategories.map((category) => ( +
  • + +
  • + ))}
  • -