Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .eslintignore

This file was deleted.

26 changes: 0 additions & 26 deletions .eslintrc.js

This file was deleted.

5 changes: 1 addition & 4 deletions .github/renovate.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
{
"extends": [
"config:base",
"github>prezly/renovate-presets:themes-nextjs"
]
"extends": ["config:base", "github>prezly/renovate-presets:themes-nextjs"]
}
4 changes: 0 additions & 4 deletions .prettierignore

This file was deleted.

1 change: 0 additions & 1 deletion .prettierrc.js

This file was deleted.

3 changes: 0 additions & 3 deletions .stylelintrc.json

This file was deleted.

8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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].

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
52 changes: 52 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -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"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disabling useExhaustiveDependencies could lead to React Hook dependency issues and potential bugs. This rule helps catch missing dependencies in useEffect, useMemo, and useCallback hooks. Consider enabling this rule and fixing the violations instead.

},
"security": {
"noDangerouslySetInnerHtml": "off"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disabling noDangerouslySetInnerHtml removes an important security check. This rule helps prevent XSS vulnerabilities. If you need to use dangerouslySetInnerHTML, it should be done carefully with proper sanitization.

},
"style": {
"noNonNullAssertion": "off",
"useNodejsImportProtocol": "off"
},
"suspicious": {
"noExplicitAny": "off",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disabling noExplicitAny removes type safety checks. This could lead to less type-safe code. Consider enabling this rule and gradually fixing any types with proper TypeScript types.

"noImplicitAnyLet": "off",
"noShadowRestrictedNames": "off"
}
}
}
}
2 changes: 1 addition & 1 deletion components/CategoriesBar/CategoriesBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good change - Number.parseInt() is preferred over the global parseInt() function for better clarity and consistency.


if (containerRef.current.scrollWidth <= containerWidthWithoutPadding) {
return [categories, []];
Expand Down
2 changes: 1 addition & 1 deletion components/ContentRenderer/components/Attachment/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good change - Number.parseInt() is preferred over the global parseInt() function.


while (n >= 1024) {
n /= 1024;
Expand Down
2 changes: 1 addition & 1 deletion components/ContentRenderer/components/Gallery.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand Down
2 changes: 1 addition & 1 deletion components/ContentRenderer/components/Image.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
2 changes: 1 addition & 1 deletion components/NotificationsBar/LinkedText.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type ReactElement } from 'react';
import type { ReactElement } from 'react';

interface Props {
links: Link[];
Expand Down
2 changes: 1 addition & 1 deletion components/NotificationsBar/NotificationsBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down
2 changes: 1 addition & 1 deletion components/RichText/Html.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand Down
2 changes: 1 addition & 1 deletion modules/Gallery/Gallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function Gallery({ gallery }: Props) {
const metaDescription = useGalleryPageMetaDescription(gallery);

useEffect(() => {
if (typeof window !== undefined) {
if (typeof window !== 'undefined') {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition will always be true. typeof window returns a string, so it will never be undefined (the value). This should be typeof window !== 'undefined' to check if the window object exists. This is a critical bug that could cause issues in SSR environments.

setUrl(window.location.href);
}
}, []);
Expand Down
27 changes: 12 additions & 15 deletions modules/Layout/Header/CategoriesDropdown/CategoriesDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,18 @@ function CategoriesDropdown({

return (
<>
{showAllCategoriesOnMobile && (
<>
{filteredCategories.map((category) => (
<li
key={category.id}
className={classNames(navigationItemClassName, styles.mobileCategory)}
>
<CategoryButton
category={category}
navigationButtonClassName={navigationButtonClassName}
/>
</li>
))}
</>
)}
{showAllCategoriesOnMobile &&
filteredCategories.map((category) => (
<li
key={category.id}
className={classNames(navigationItemClassName, styles.mobileCategory)}
>
<CategoryButton
category={category}
navigationButtonClassName={navigationButtonClassName}
/>
</li>
))}
<li
className={classNames(navigationItemClassName, {
[styles.desktopCategories]: showAllCategoriesOnMobile,
Expand Down
2 changes: 1 addition & 1 deletion modules/Layout/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ function Header({ hasError }: Props) {
})}
>
<div className="container">
<nav role="navigation" className={styles.header}>
<nav className={styles.header}>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the role="navigation" attribute reduces accessibility. The <nav> element already has implicit navigation role, but explicit roles are often preferred for screen readers and accessibility tools. Consider keeping this attribute.

<Link
href="/"
locale={getLinkLocaleSlug()}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ACTIONS, useAnalytics } from '@prezly/analytics-nextjs';
import { getLanguageDisplayName, getUsedLanguages, LocaleObject } from '@prezly/theme-kit-core';
import { LocaleObject, getLanguageDisplayName, getUsedLanguages } from '@prezly/theme-kit-core';
import {
useCurrentLocale,
useCurrentStory,
Expand Down
2 changes: 1 addition & 1 deletion modules/Search/components/Hit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { Highlight } from 'react-instantsearch-dom';
import { CategoriesList, StoryImage, StoryPublicationDate } from '@/components';
import { useThemeSettings } from '@/hooks';

import styles from './Hit.module.scss';
import cardStyles from '@/components/StoryCards/StoryCard.module.scss';
import styles from './Hit.module.scss';

interface Props {
hit: Hit<{ attributes: IndexedStory }>;
Expand Down
2 changes: 1 addition & 1 deletion modules/Search/components/Results.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import { Button } from '@/ui';
import { useAlgoliaState } from './AlgoliaStateContext';
import Hit from './Hit';

import styles from './Results.module.scss';
import containerStyles from '@/modules/InfiniteStories/InfiniteStories.module.scss';
import listStyles from '@/modules/InfiniteStories/StoriesList.module.scss';
import styles from './Results.module.scss';

type SearchHit = HitType<{ attributes: IndexedStory }>;

Expand Down
2 changes: 1 addition & 1 deletion modules/Search/components/SearchInput.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ACTIONS, useAnalytics } from '@prezly/analytics-nextjs';
import { translations } from '@prezly/theme-kit-intl';
import { useDebouncedCallback } from '@react-hookz/web';
import { type ChangeEvent } from 'react';
import type { ChangeEvent } from 'react';
import type { SearchBoxExposed, SearchBoxProvided } from 'react-instantsearch-core';
import { connectSearchBox } from 'react-instantsearch-dom';
import { useIntl } from 'react-intl';
Expand Down
2 changes: 1 addition & 1 deletion modules/Stories/Stories.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type PaginationProps } from '@prezly/theme-kit-nextjs';
import type { PaginationProps } from '@prezly/theme-kit-nextjs';

import type { StoryWithImage } from 'types';

Expand Down
Loading
Loading