diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 38a7ddc..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,53 +0,0 @@ -/** @type {import('eslint').Linter.Config} */ -const config = { - parser: '@typescript-eslint/parser', - parserOptions: { - project: true, - }, - plugins: ['@typescript-eslint', 'drizzle'], - extends: [ - 'next/core-web-vitals', - 'plugin:@typescript-eslint/recommended-type-checked', - 'plugin:@typescript-eslint/stylistic-type-checked', - 'prettier', - ], - rules: { - '@typescript-eslint/array-type': 'off', - '@typescript-eslint/consistent-type-definitions': 'off', - '@typescript-eslint/consistent-type-imports': [ - 'warn', - { - prefer: 'type-imports', - fixStyle: 'inline-type-imports', - }, - ], - '@typescript-eslint/no-unused-vars': [ - 'warn', - { - argsIgnorePattern: '^_', - }, - ], - '@typescript-eslint/require-await': 'off', - '@typescript-eslint/no-misused-promises': [ - 'error', - { - checksVoidReturn: { - attributes: false, - }, - }, - ], - 'drizzle/enforce-delete-with-where': [ - 'error', - { - drizzleObjectName: ['db', 'ctx.db'], - }, - ], - 'drizzle/enforce-update-with-where': [ - 'error', - { - drizzleObjectName: ['db', 'ctx.db'], - }, - ], - }, -}; -module.exports = config; diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 1fd86be..435dc44 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,13 +1,17 @@ name: Lint -on: push +on: + push: + jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: oven-sh/setup-bun@v1 + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Biome + uses: biomejs/setup-biome@v2 with: - bun-version: 1.1.12 - - run: bun install - - run: bun lint + version: latest + - name: Run Biome + run: biome ci . diff --git a/.husky/_/pre-commit b/.husky/_/pre-commit new file mode 100755 index 0000000..3fbf5f9 --- /dev/null +++ b/.husky/_/pre-commit @@ -0,0 +1,60 @@ +#!/bin/sh + +if [ "$LEFTHOOK_VERBOSE" = "1" -o "$LEFTHOOK_VERBOSE" = "true" ]; then + set -x +fi + +if [ "$LEFTHOOK" = "0" ]; then + exit 0 +fi + +call_lefthook() +{ + if test -n "$LEFTHOOK_BIN" + then + "$LEFTHOOK_BIN" "$@" + elif lefthook -h >/dev/null 2>&1 + then + lefthook "$@" + else + dir="$(git rev-parse --show-toplevel)" + osArch=$(uname | tr '[:upper:]' '[:lower:]') + cpuArch=$(uname -m | sed 's/aarch64/arm64/;s/x86_64/x64/') + if test -f "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook" + then + "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook" "$@" + elif test -f "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook" + then + "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook" "$@" + elif test -f "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook" + then + "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook" "$@" + elif test -f "$dir/node_modules/lefthook/bin/index.js" + then + "$dir/node_modules/lefthook/bin/index.js" "$@" + + elif bundle exec lefthook -h >/dev/null 2>&1 + then + bundle exec lefthook "$@" + elif yarn lefthook -h >/dev/null 2>&1 + then + yarn lefthook "$@" + elif pnpm lefthook -h >/dev/null 2>&1 + then + pnpm lefthook "$@" + elif swift package plugin lefthook >/dev/null 2>&1 + then + swift package --disable-sandbox plugin lefthook "$@" + elif command -v mint >/dev/null 2>&1 + then + mint run csjones/lefthook-plugin "$@" + elif command -v npx >/dev/null 2>&1 + then + npx lefthook "$@" + else + echo "Can't find lefthook in PATH" + fi + fi +} + +call_lefthook run "pre-commit" "$@" diff --git a/.husky/_/prepare-commit-msg b/.husky/_/prepare-commit-msg new file mode 100755 index 0000000..e8e8dda --- /dev/null +++ b/.husky/_/prepare-commit-msg @@ -0,0 +1,60 @@ +#!/bin/sh + +if [ "$LEFTHOOK_VERBOSE" = "1" -o "$LEFTHOOK_VERBOSE" = "true" ]; then + set -x +fi + +if [ "$LEFTHOOK" = "0" ]; then + exit 0 +fi + +call_lefthook() +{ + if test -n "$LEFTHOOK_BIN" + then + "$LEFTHOOK_BIN" "$@" + elif lefthook -h >/dev/null 2>&1 + then + lefthook "$@" + else + dir="$(git rev-parse --show-toplevel)" + osArch=$(uname | tr '[:upper:]' '[:lower:]') + cpuArch=$(uname -m | sed 's/aarch64/arm64/;s/x86_64/x64/') + if test -f "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook" + then + "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook" "$@" + elif test -f "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook" + then + "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook" "$@" + elif test -f "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook" + then + "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook" "$@" + elif test -f "$dir/node_modules/lefthook/bin/index.js" + then + "$dir/node_modules/lefthook/bin/index.js" "$@" + + elif bundle exec lefthook -h >/dev/null 2>&1 + then + bundle exec lefthook "$@" + elif yarn lefthook -h >/dev/null 2>&1 + then + yarn lefthook "$@" + elif pnpm lefthook -h >/dev/null 2>&1 + then + pnpm lefthook "$@" + elif swift package plugin lefthook >/dev/null 2>&1 + then + swift package --disable-sandbox plugin lefthook "$@" + elif command -v mint >/dev/null 2>&1 + then + mint run csjones/lefthook-plugin "$@" + elif command -v npx >/dev/null 2>&1 + then + npx lefthook "$@" + else + echo "Can't find lefthook in PATH" + fi + fi +} + +call_lefthook run "prepare-commit-msg" "$@" diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index ea5a55b..0000000 --- a/.husky/pre-commit +++ /dev/null @@ -1 +0,0 @@ -bunx lint-staged diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index a294968..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "recommendations": [ - "dbaeumer.vscode-eslint", - "bradlc.vscode-tailwindcss", - "lokalise.i18n-ally", - "vivaxy.vscode-conventional-commits", - "oven.bun-vscode" - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index e8f66e4..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "files.associations": { - "*.css": "tailwindcss" - }, - "tailwindCSS.experimental.classRegex": [ - ["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"], - ["cx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"] - ], - "i18n-ally.localesPaths": ["messages"], - "i18n-ally.keystyle": "nested" -} diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..c477d54 --- /dev/null +++ b/biome.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json", + "formatter": { + "enabled": true, + "indentStyle": "space" + }, + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "nursery": { + "useSortedClasses": "warn" + } + } + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "jsxQuoteStyle": "single" + } + }, + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true, + "defaultBranch": "main" + }, + "files": { + "ignore": [".next"] + } +} diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 0000000..cf9b74e --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,6 @@ +pre-commit: + commands: + check: + glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}" + stage_fixed: true + run: bunx @biomejs/biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files} diff --git a/package.json b/package.json index a51ace6..2bea4f7 100644 --- a/package.json +++ b/package.json @@ -4,20 +4,14 @@ "private": true, "type": "module", "scripts": { - "prepare": "husky", + "prepare": "lefthook install", "postbuild": "next-sitemap", "prebuild": "next telemetry disable", "build": "next build", "dev": "next dev --turbo", - "lint": "next lint && prettier --write .", + "lint": "biome check --write --unsafe", "start": "next start" }, - "lint-staged": { - "*.{js,ts,tsx}": [ - "eslint --fix", - "prettier --write" - ] - }, "dependencies": { "@libsql/client": "^0.6.2", "@radix-ui/react-avatar": "^1.1.0", @@ -55,22 +49,13 @@ "zod": "^3.23.8" }, "devDependencies": { - "@trivago/prettier-plugin-sort-imports": "^4.3.0", - "@types/eslint": "^8.56.10", + "@biomejs/biome": "1.8.3", "@types/node": "^20.14.8", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "@typescript-eslint/parser": "^7.13.1", "drizzle-kit": "^0.22.7", - "eslint": "^8.57.0", - "eslint-config-next": "^14.2.4", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-drizzle": "^0.2.3", - "lint-staged": "^15.2.7", + "lefthook": "^1.7.14", "postcss": "^8.4.38", - "prettier": "^3.3.2", - "prettier-plugin-tailwindcss": "^0.6.5", "tailwind-scrollbar": "^3.1.0", "tailwindcss": "^3.4.4", "tailwindcss-animate": "^1.0.7", diff --git a/prettier.config.js b/prettier.config.js deleted file mode 100644 index c34bef6..0000000 --- a/prettier.config.js +++ /dev/null @@ -1,23 +0,0 @@ -/** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions & import("@trivago/prettier-plugin-sort-imports").PluginConfig} */ -const config = { - semi: true, - singleQuote: true, - tabWidth: 2, - useTabs: false, - jsxSingleQuote: true, - importOrder: [ - '^[./]', - '^@/(lib|styles)/(.*)$', - '^@/hooks/(.*)$', - '^@/components/(.*)$', - ], - importOrderSeparation: true, - importOrderSortSpecifiers: true, - tailwindFunctions: ['cx', 'cva'], - plugins: [ - '@trivago/prettier-plugin-sort-imports', - 'prettier-plugin-tailwindcss', - ], -}; - -export default config; diff --git a/src/app/[locale]/(default)/news/(header)/page.tsx b/src/app/[locale]/(default)/news/(header)/page.tsx index 44255c9..30444ab 100644 --- a/src/app/[locale]/(default)/news/(header)/page.tsx +++ b/src/app/[locale]/(default)/news/(header)/page.tsx @@ -1,7 +1,7 @@ import { articleMockData as articleData } from '@/mock-data/article'; import { useTranslations } from 'next-intl'; import { getTranslations, unstable_setRequestLocale } from 'next-intl/server'; -import { createSearchParamsCache, parseAsInteger } from 'nuqs/parsers'; +import { createSearchParamsCache, parseAsInteger } from 'nuqs/server'; import { Suspense } from 'react'; import { PaginationCarousel } from '@/components/layout/PaginationCarousel'; diff --git a/src/app/[locale]/(default)/news/[article]/page.tsx b/src/app/[locale]/(default)/news/[article]/page.tsx index 0b888b3..c4f6e37 100644 --- a/src/app/[locale]/(default)/news/[article]/page.tsx +++ b/src/app/[locale]/(default)/news/[article]/page.tsx @@ -46,12 +46,16 @@ export default function ArticlePage({ return notFound(); } - const { minutes } = readingTime(article.content!); - const author = authorData[0]!; + const { minutes } = readingTime(article.content as string); // assert because its a mock data file + const author = authorData[0] as { + name: string; + photoUrl: string; + initials: string; + }; // same as above return (
-
+
- {article.views + ' ' + t('views')} + {`${article.views} ${t('views')}`}
{article.content}
diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx index dd826b2..24bfeeb 100644 --- a/src/app/[locale]/layout.tsx +++ b/src/app/[locale]/layout.tsx @@ -86,7 +86,7 @@ export default function LocaleLayout({ > -
+
{children}
diff --git a/src/components/assets/Logo.tsx b/src/components/assets/Logo.tsx index e0074cf..a8a9f09 100644 --- a/src/components/assets/Logo.tsx +++ b/src/components/assets/Logo.tsx @@ -18,7 +18,7 @@ function Logo({ className, ...rest }: { className?: string }) { d='M46.697,71.821l-1.193-2.641l4.751-1.918l-0.56-9.096c-0.026-0.418,0.131-0.826,0.43-1.121l6.133-6.028 c0.299-0.295,0.71-0.447,1.131-0.411l9.086,0.732l1.573-3.699l-6.829-6.041c-0.315-0.278-0.493-0.68-0.49-1.1l0.093-8.594 c0.004-0.42,0.19-0.817,0.511-1.089l6.938-5.893l-1.507-3.734l-9.085,0.558c-0.418,0.03-0.828-0.131-1.122-0.43l-6.029-6.131 c-0.294-0.299-0.444-0.713-0.411-1.132l0.734-9.085l-3.709-1.575l-6.033,6.822c-0.278,0.314-0.645,0.512-1.099,0.489l-8.604-0.082 c-0.419-0.004-0.816-0.19-1.088-0.51l-5.904-6.931l-3.725,1.499l0.559,9.085c0.03,0.5-0.254,0.915-0.608,1.27 c-1.073,1.074-5.148,5.041-5.813,5.705c-0.354,0.354-0.773,0.634-1.281,0.586L4.47,20.602l-1.575,3.699l6.819,6.022 c0.315,0.279,0.494,0.68,0.49,1.1l-0.082,8.614c-0.004,0.42-0.189,0.817-0.51,1.09L2.673,47.03l1.507,3.726l9.096-0.56 c0.415-0.035,0.829,0.132,1.123,0.431l6.019,6.142c0.294,0.301,0.443,0.713,0.409,1.133l-0.732,9.064l4.67,1.992l-1.136,2.664 l-5.631-2.401c-0.574-0.244-0.927-0.828-0.875-1.449l0.766-9.446l-5.096-5.197L3.316,53.71c-0.619,0.022-1.198-0.324-1.432-0.902 l-2.289-5.661C-0.638,46.569-0.475,45.905,0,45.5l7.232-6.153l0.069-7.291l-7.107-6.276c-0.468-0.413-0.618-1.078-0.374-1.653 l2.392-5.619c0.243-0.574,0.82-0.934,1.448-0.877l9.325,0.744c0.986-0.986,4.042-3.944,5.322-5.224l-0.574-9.336 c-0.039-0.621,0.326-1.199,0.905-1.432l5.659-2.279c0.578-0.232,1.239-0.069,1.645,0.405l6.151,7.222l7.282,0.07l6.286-7.108 c0.412-0.467,1.077-0.619,1.65-0.374l5.632,2.391c0.574,0.244,0.929,0.828,0.877,1.45l-0.765,9.467l5.102,5.188l9.469-0.582 c0.625-0.045,1.199,0.325,1.432,0.903l2.29,5.671c0.232,0.578,0.068,1.242-0.406,1.646l-7.232,6.143l-0.076,7.271l7.114,6.295 c0.468,0.414,0.617,1.079,0.374,1.651l-2.392,5.621c-0.244,0.574-0.823,0.921-1.45,0.877l-9.465-0.764l-5.189,5.101l0.584,9.478 c0.039,0.625-0.326,1.201-0.905,1.435L46.697,71.821z' /> diff --git a/src/components/layout/Footer.tsx b/src/components/layout/Footer.tsx index 815a0b6..b2dd899 100644 --- a/src/components/layout/Footer.tsx +++ b/src/components/layout/Footer.tsx @@ -18,8 +18,8 @@ function Footer() { const t = useTranslations('layout'); const year = new Date().getFullYear(); return ( -