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) => (
-
-