diff --git a/.gitignore b/.gitignore index 5899c04..644cc8e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .* !.gitignore +!.pre-commit-config.yaml # Cache node_modules diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..4e128de --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,23 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.2.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files +- repo: https://github.com/compilerla/conventional-pre-commit + rev: v3.4.0 + hooks: + - id: conventional-pre-commit + stages: [commit-msg] + args: [feat, fix, chore, test, build, merge] +- repo: local + hooks: + - id: eslint + name: eslint + entry: bash -c 'npx eslint' + language: system + + types: [javascript] + pass_filenames: false diff --git a/README.md b/README.md index e10ac61..77f68d6 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,27 @@ directory. The website will be built statically in `build/`. Note that changing ## Developing -Install dependencies with `npm install` (or `pnpm install` or `yarn`). Then start the dev server with +Install [pre-commit](https://pre-commit.com/). + +Install dependencies with `npm install` (or `pnpm install` or `yarn`). Then +start the dev server with ```bash npm run dev [-- --open] ``` +### Formatting + +``` bash +npx run eslint +``` + +### Testing + +To run tests +``` bash +npx playwright test +``` + +All tests must have the suffix `.spec.[jt]s`. Be cautious while updating +`playwright` since the versions in `nixpkgs` and `node` must exactly match. diff --git a/components.json b/components.json index 8fed8f7..ce35209 100644 --- a/components.json +++ b/components.json @@ -11,4 +11,4 @@ "utils": "$lib/utils" }, "typescript": true -} \ No newline at end of file +} diff --git a/eslint.config.js b/eslint.config.js index 62dbd03..1240824 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,33 +1,29 @@ -import js from '@eslint/js'; -import ts from 'typescript-eslint'; -import svelte from 'eslint-plugin-svelte'; -import prettier from 'eslint-config-prettier'; -import globals from 'globals'; +import globals from "globals"; +import pluginJs from "@eslint/js"; +import tseslint from "typescript-eslint"; + -/** @type {import('eslint').Linter.Config[]} */ export default [ - js.configs.recommended, - ...ts.configs.recommended, - ...svelte.configs['flat/recommended'], - prettier, - ...svelte.configs['flat/prettier'], - { - languageOptions: { - globals: { - ...globals.browser, - ...globals.node - } - } - }, - { - files: ['**/*.svelte'], - languageOptions: { - parserOptions: { - parser: ts.parser - } - } - }, - { - ignores: ['build/', '.svelte-kit/', 'dist/'] - } + { + files: ["**/*.{js,mjs,cjs,ts}"], + }, + { + ignores: ["build/", ".svelte-kit/"], + }, + { + languageOptions: { globals: {...globals.browser, ...globals.node} } + }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + { + rules: { + "@typescript-eslint/no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + }, + ], + }, + }, ]; diff --git a/flake.nix b/flake.nix index d98fc0b..57199f3 100644 --- a/flake.nix +++ b/flake.nix @@ -21,6 +21,7 @@ "x86_64-darwin" ]; perSystem = { system, pkgs, ... }: let + nodejs = pkgs.nodejs_22; module = { lib, config, @@ -61,8 +62,15 @@ }; }; devShells.default = pkgs.mkShell { + packages = [ + pkgs.playwright-driver.browsers + ]; + PLAYWRIGHT_NODEJS_PATH = "${nodejs}/bin/node"; + PLAYWRIGHT_BROWSERS_PATH = "${pkgs.playwright-driver.browsers}"; + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = 1; + PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS = 1; buildInputs = [ - pkgs.nodejs_22 + nodejs ]; }; }; diff --git a/package-lock.json b/package-lock.json index 3a8c52b..c071eea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,8 @@ "tailwind-variants": "^0.2.1" }, "devDependencies": { - "@playwright/test": "^1.28.1", + "@eslint/js": "^9.11.1", + "@playwright/test": "^1.40.0", "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-static": "^3.0.5", "@sveltejs/kit": "^2.0.0", @@ -27,10 +28,10 @@ "@tailwindcss/typography": "^0.5.15", "@types/eslint": "^9.6.0", "autoprefixer": "^10.4.20", - "eslint": "^9.0.0", + "eslint": "^9.11.1", "eslint-config-prettier": "^9.1.0", "eslint-plugin-svelte": "^2.36.0", - "globals": "^15.0.0", + "globals": "^15.9.0", "mdsvex": "^0.12.3", "mdsvex-relative-images": "^1.0.3", "prettier": "^3.1.1", @@ -39,8 +40,8 @@ "svelte": "^4.2.7", "svelte-check": "^4.0.0", "tailwindcss": "^3.4.9", - "typescript": "^5.0.0", - "typescript-eslint": "^8.0.0", + "typescript": "5.5", + "typescript-eslint": "^8.7.0", "unist-util-visit": "^5.0.0", "vite": "^5.0.3", "vitest": "^2.0.0" @@ -487,6 +488,16 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/core": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", @@ -523,10 +534,11 @@ } }, "node_modules/@eslint/js": { - "version": "9.10.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", - "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz", + "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -541,10 +553,11 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.1.0.tgz", - "integrity": "sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", "dev": true, + "license": "Apache-2.0", "dependencies": { "levn": "^0.4.1" }, @@ -759,36 +772,20 @@ } }, "node_modules/@playwright/test": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.0.tgz", - "integrity": "sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA==", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.0.tgz", + "integrity": "sha512-PdW+kn4eV99iP5gxWNSDQCbhMaDVej+RXL5xr6t04nbKLCBwYtA046t7ofoczHOm8u6c+45hpDKQVZqtqwkeQg==", + "deprecated": "Please update to the latest version of Playwright to test up-to-date browsers.", "dev": true, + "license": "Apache-2.0", "dependencies": { - "playwright": "1.47.0" + "playwright": "1.40.0" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=18" - } - }, - "node_modules/@playwright/test/node_modules/playwright": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0.tgz", - "integrity": "sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==", - "dev": true, - "dependencies": { - "playwright-core": "1.47.0" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" + "node": ">=16" } }, "node_modules/@polka/url": { @@ -1183,16 +1180,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.5.0.tgz", - "integrity": "sha512-lHS5hvz33iUFQKuPFGheAB84LwcJ60G8vKnEhnfcK1l8kGVLro2SFYW6K0/tj8FUhRJ0VHyg1oAfg50QGbPPHw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz", + "integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.5.0", - "@typescript-eslint/type-utils": "8.5.0", - "@typescript-eslint/utils": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0", + "@typescript-eslint/scope-manager": "8.7.0", + "@typescript-eslint/type-utils": "8.7.0", + "@typescript-eslint/utils": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1216,15 +1214,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.5.0.tgz", - "integrity": "sha512-gF77eNv0Xz2UJg/NbpWJ0kqAm35UMsvZf1GHj8D9MRFTj/V3tAciIWXfmPLsAAF/vUlpWPvUDyH1jjsr0cMVWw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.7.0.tgz", + "integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.5.0", - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/typescript-estree": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0", + "@typescript-eslint/scope-manager": "8.7.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/typescript-estree": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0", "debug": "^4.3.4" }, "engines": { @@ -1244,13 +1243,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", - "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz", + "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0" + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1261,13 +1261,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.5.0.tgz", - "integrity": "sha512-N1K8Ix+lUM+cIDhL2uekVn/ZD7TZW+9/rwz8DclQpcQ9rk4sIL5CAlBC0CugWKREmDjBzI/kQqU4wkg46jWLYA==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz", + "integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.5.0", - "@typescript-eslint/utils": "8.5.0", + "@typescript-eslint/typescript-estree": "8.7.0", + "@typescript-eslint/utils": "8.7.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1285,10 +1286,11 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", - "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz", + "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -1298,13 +1300,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", - "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz", + "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1330,6 +1333,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -1339,6 +1343,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -1350,15 +1355,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", - "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz", + "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.5.0", - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/typescript-estree": "8.5.0" + "@typescript-eslint/scope-manager": "8.7.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/typescript-estree": "8.7.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1372,12 +1378,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", - "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz", + "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/types": "8.7.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -1393,6 +1400,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2089,20 +2097,24 @@ } }, "node_modules/eslint": { - "version": "9.10.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.10.0.tgz", - "integrity": "sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==", + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz", + "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.10.0", - "@eslint/plugin-kit": "^0.1.0", + "@eslint/js": "9.11.1", + "@eslint/plugin-kit": "^0.2.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -2249,6 +2261,13 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, "node_modules/esm-env": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz", @@ -2610,6 +2629,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -2633,7 +2653,8 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/has-flag": { "version": "4.0.0", @@ -3485,16 +3506,36 @@ "node": ">= 6" } }, - "node_modules/playwright-core": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0.tgz", - "integrity": "sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==", + "node_modules/playwright": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.0.tgz", + "integrity": "sha512-gyHAgQjiDf1m34Xpwzaqb76KgfzYrhK7iih+2IzcOCoZWr/8ZqmdBw+t0RU85ZmfJMgtgAiNtBQ/KS2325INXw==", "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.40.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.0.tgz", + "integrity": "sha512-fvKewVJpGeca8t0ipM56jkVSU6Eo0RmFvQ/MaCQNDYm+sdvKkMBBWTE1FdeMqIdumRaXXjZChWHvIzCGM/tA/Q==", + "dev": true, + "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=16" } }, "node_modules/postcss": { @@ -4645,6 +4686,7 @@ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -4675,10 +4717,11 @@ } }, "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4688,14 +4731,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.5.0.tgz", - "integrity": "sha512-uD+XxEoSIvqtm4KE97etm32Tn5MfaZWgWfMMREStLxR6JzvHkc2Tkj7zhTEK5XmtpTmKHNnG8Sot6qDfhHtR1Q==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.7.0.tgz", + "integrity": "sha512-nEHbEYJyHwsuf7c3V3RS7Saq+1+la3i0ieR3qP0yjqWSzVmh8Drp47uOl9LjbPANac4S7EFSqvcYIKXUUwIfIQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.5.0", - "@typescript-eslint/parser": "8.5.0", - "@typescript-eslint/utils": "8.5.0" + "@typescript-eslint/eslint-plugin": "8.7.0", + "@typescript-eslint/parser": "8.7.0", + "@typescript-eslint/utils": "8.7.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/package.json b/package.json index 855fcfb..aa9cd14 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "prepare": "svelte-kit sync" }, "devDependencies": { - "@playwright/test": "^1.28.1", + "@eslint/js": "^9.11.1", + "@playwright/test": "^1.40.0", "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-static": "^3.0.5", "@sveltejs/kit": "^2.0.0", @@ -24,10 +25,10 @@ "@tailwindcss/typography": "^0.5.15", "@types/eslint": "^9.6.0", "autoprefixer": "^10.4.20", - "eslint": "^9.0.0", + "eslint": "^9.11.1", "eslint-config-prettier": "^9.1.0", "eslint-plugin-svelte": "^2.36.0", - "globals": "^15.0.0", + "globals": "^15.9.0", "mdsvex": "^0.12.3", "mdsvex-relative-images": "^1.0.3", "prettier": "^3.1.1", @@ -36,8 +37,8 @@ "svelte": "^4.2.7", "svelte-check": "^4.0.0", "tailwindcss": "^3.4.9", - "typescript": "^5.0.0", - "typescript-eslint": "^8.0.0", + "typescript": "5.5", + "typescript-eslint": "^8.7.0", "unist-util-visit": "^5.0.0", "vite": "^5.0.3", "vitest": "^2.0.0" diff --git a/src/app.css b/src/app.css index 0d90f55..193a062 100644 --- a/src/app.css +++ b/src/app.css @@ -4,73 +4,73 @@ @tailwind base; @tailwind components; @tailwind utilities; - + @layer base { :root { --background: 0 0% 90%; --foreground: 20 14.3% 4.1%; - + --muted: 60 4.8% 95.9%; --muted-foreground: 25 5.3% 44.7%; - + --popover: 0 0% 100%; --popover-foreground: 20 14.3% 4.1%; - + --card: 0 0% 100%; --card-foreground: 20 14.3% 4.1%; - + --border: 20 5.9% 90%; --input: 20 5.9% 90%; - + --primary: 24 9.8% 10%; --primary-foreground: 60 9.1% 97.8%; - + --secondary: 60 4.8% 95.9%; --secondary-foreground: 24 9.8% 10%; - + --accent: 60 4.8% 95.9%; --accent-foreground: 24 9.8% 10%; - + --destructive: 0 72.2% 50.6%; --destructive-foreground: 60 9.1% 97.8%; - + --ring: 20 14.3% 4.1%; - + --radius: 0.5rem; } - + .dark { --background: 20 14.3% 4.1%; --foreground: 60 9.1% 97.8%; - + --muted: 12 6.5% 15.1%; --muted-foreground: 24 5.4% 63.9%; - + --popover: 20 14.3% 4.1%; --popover-foreground: 60 9.1% 97.8%; - + --card: 20 14.3% 4.1%; --card-foreground: 60 9.1% 97.8%; - + --border: 12 6.5% 15.1%; --input: 12 6.5% 15.1%; - + --primary: 60 9.1% 97.8%; --primary-foreground: 24 9.8% 10%; - + --secondary: 12 6.5% 15.1%; --secondary-foreground: 60 9.1% 97.8%; - + --accent: 12 6.5% 15.1%; --accent-foreground: 60 9.1% 97.8%; - + --destructive: 0 62.8% 30.6%; --destructive-foreground: 60 9.1% 97.8%; - + --ring: 24 5.7% 82.9%; } } - + @layer base { * { @apply border-border; diff --git a/src/content/archives.md b/src/content/archives.md index 4fe3b2f..c2a6133 100644 --- a/src/content/archives.md +++ b/src/content/archives.md @@ -1,4 +1,3 @@ # Archives Archives live here - diff --git a/src/content/home.md b/src/content/home.md index c3d21ff..fbed528 100644 --- a/src/content/home.md +++ b/src/content/home.md @@ -23,5 +23,3 @@ Strongest of Gensokyo for i in range(9): print("this is python") ``` - - diff --git a/src/lib/markdown.js b/src/lib/markdown.js index 8a37276..97d103c 100644 --- a/src/lib/markdown.js +++ b/src/lib/markdown.js @@ -12,7 +12,7 @@ const alertRegex = /^:>(NOTE|TIP|IMPORTANT|WARNING|CAUTION)/i; */ function remarkAlert/*: Plugin<[Option?], Root> = */() /*=>*/ { return (tree) => { - visit(tree, "blockquote", (node, index, parent) => { + visit(tree, "blockquote", (node, _index, _parent) => { let alertType = ''; let title = ''; let isNext = true; @@ -48,7 +48,7 @@ function remarkAlert/*: Plugin<[Option?], Root> = */() /*=>*/ { } return item; }); - if (!!alertType) { + if (alertType) { node.data = { hName: "div", hProperties: { diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 8871245..28aa936 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -59,4 +59,4 @@ export const flyAndScale = ( }, easing: cubicOut }; -}; \ No newline at end of file +}; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 3f3b409..89861ee 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -65,7 +65,7 @@ -
+
@@ -86,7 +86,7 @@
-
+
{ +export const load: PageLoad = async (_) => { const post = await import(`$content/home.md`); if (!post) throw error(404); - const { name, date } = post.metadata; + const { name } = post.metadata; const Content = post.default; return { diff --git a/src/routes/archives/+page.ts b/src/routes/archives/+page.ts index 6dae9d3..efeea04 100644 --- a/src/routes/archives/+page.ts +++ b/src/routes/archives/+page.ts @@ -1,7 +1,6 @@ -import { error } from '@sveltejs/kit'; import type { PageLoad } from './$types'; -export const load: PageLoad = async ({ params }) => { +export const load: PageLoad = async (_) => { const post = await import("$content/archives.md"); const Content = post.default; diff --git a/src/routes/post/+page.server.ts b/src/routes/post/+page.server.ts index 283c681..368c4b9 100644 --- a/src/routes/post/+page.server.ts +++ b/src/routes/post/+page.server.ts @@ -1,6 +1,6 @@ import type { PageLoad } from './$types'; -export const load: PageLoad = async ({ params }) => { +export const load: PageLoad = async (_) => { const allPostFiles = import.meta.glob('$content/post/*.md'); const iterablePostFiles = Object.entries(allPostFiles); diff --git a/src/routes/post/[slug]/+page.ts b/src/routes/post/[slug]/+page.ts index de6d407..7c82d3a 100644 --- a/src/routes/post/[slug]/+page.ts +++ b/src/routes/post/[slug]/+page.ts @@ -15,7 +15,7 @@ export const load: PageLoad = async ({ params }) => { Content, }; } - catch(e) { + catch { error(404, `Could not find post ${params.slug}`) } } diff --git a/static/favicon.svg b/static/favicon.svg index a135916..a818f6b 100644 --- a/static/favicon.svg +++ b/static/favicon.svg @@ -1 +1 @@ -logo \ No newline at end of file +logo diff --git a/tailwind.config.ts b/tailwind.config.ts index 514354c..0b7da4c 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,5 +1,6 @@ -import { fontFamily } from "tailwindcss/defaultTheme"; +//import { fontFamily } from "tailwindcss/defaultTheme"; import type { Config } from "tailwindcss"; +import typography from '@tailwindcss/typography'; const config: Config = { darkMode: ["class"], @@ -103,12 +104,12 @@ const config: Config = { sans: '"Source Han Sans SC", "Source Han Sans CN","Noto Sans CJK SC", "Noto Sans", -apple-system, "Helvetica Neue", Helvetica, "Nimbus Sans L", Arial, "Liberation Sans", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Wenquanyi Micro Hei", "WenQuanYi Zen Hei", "ST Heiti", SimHei, "WenQuanYi Zen Hei Sharp", sans-serif', //For varible font usage sometimes // 'serif': '"Source Han Serif CN Variable", "Source Han Serif SC", "Source Han Serif CN","Noto Serif CJK SC", "Songti SC", STSong, "AR PL New Sung", "AR PL SungtiL GB", NSimSun, SimSun, "TW\-Sung", "WenQuanYi Bitmap Song", "AR PL UMing CN", "AR PL UMing HK", "AR PL UMing TW", "AR PL UMing TW MBE", PMingLiU, MingLiU, serif', - serif: '"Source Han Serif SC", "Source Han Serif CN","Noto Serif CJK SC", "Songti SC", STSong, "AR PL New Sung", "AR PL SungtiL GB", NSimSun, SimSun, "TW\-Sung", "WenQuanYi Bitmap Song", "AR PL UMing CN", "AR PL UMing HK", "AR PL UMing TW", "AR PL UMing TW MBE", PMingLiU, MingLiU, serif', - cursive: 'FancyTitleFont,"Source Han Serif SC", "Source Han Serif CN", "Noto Serif CJK SC", "Songti SC", STSong, "AR PL New Sung", "AR PL SungtiL GB", NSimSun, SimSun, "TW\-Sung", "WenQuanYi Bitmap Song", "AR PL UMing CN", "AR PL UMing HK", "AR PL UMing TW", "AR PL UMing TW MBE", PMingLiU, MingLiU, serif', + serif: '"Source Han Serif SC", "Source Han Serif CN","Noto Serif CJK SC", "Songti SC", STSong, "AR PL New Sung", "AR PL SungtiL GB", NSimSun, SimSun, "TW-Sung", "WenQuanYi Bitmap Song", "AR PL UMing CN", "AR PL UMing HK", "AR PL UMing TW", "AR PL UMing TW MBE", PMingLiU, MingLiU, serif', + cursive: 'FancyTitleFont,"Source Han Serif SC", "Source Han Serif CN", "Noto Serif CJK SC", "Songti SC", STSong, "AR PL New Sung", "AR PL SungtiL GB", NSimSun, SimSun, "TW-Sung", "WenQuanYi Bitmap Song", "AR PL UMing CN", "AR PL UMing HK", "AR PL UMing TW", "AR PL UMing TW MBE", PMingLiU, MingLiU, serif', mono: "'Fira Code','Cascadia Code',Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New','Sarasa Mono SC','Noto Sans CJK SC','monospace', monospace" }, typography: ((theme) => { - let markdownCommon = { + const markdownCommon = { h1: { color: theme('colors.eucalyptus.700'), }, @@ -149,7 +150,7 @@ const config: Config = { } }, plugins: [ - require('@tailwindcss/typography'), + typography, ], }; diff --git a/tests/home.spec.ts b/tests/home.spec.ts new file mode 100644 index 0000000..f2cf542 --- /dev/null +++ b/tests/home.spec.ts @@ -0,0 +1,22 @@ +import { expect, test } from '@playwright/test'; + +test('home page has main and background', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('main')).toBeVisible(); + await expect(page.locator('#background')).toBeVisible(); +}); +test('home page bio button', async ({ page }) => { + await page.goto('/'); + await page.getByRole('link', { name : 'Bio' }).click(); + await expect(page).toHaveURL('/#bio'); +}); +test('home page blog button', async ({ page }) => { + await page.goto('/'); + await page.getByText('Blog').click(); + await expect(page).toHaveURL(/post/); +}); +test('home page archives button', async ({ page }) => { + await page.goto('/'); + await page.getByText('Archives').click(); + await expect(page).toHaveURL(/archives/); +}); diff --git a/tests/test.ts b/tests/test.ts deleted file mode 100644 index 9985ce1..0000000 --- a/tests/test.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { expect, test } from '@playwright/test'; - -test('home page has expected h1', async ({ page }) => { - await page.goto('/'); - await expect(page.locator('h1')).toBeVisible(); -});