refactor(other): eslint config it4c advanced (#650)

* rename test:lint:eslint to lint and update eslint-config-it4c package

* simplify config and make it ts

* jest update & ts

* suppress server logging output in tests

* remove test node_env as it is default for jest

* use eslint-config-it4c

* packages = module

* fix tailwind as ts

* eslitn autofix

* more fixes

* tsconfig & some eslint rules

* fixes

* more fixes

* more exceptions

* do not allow warnings

* fix config

* ignore vuepress generated configs

* ts include fix
This commit is contained in:
Ulf Gebhardt 2026-02-14 17:34:37 +01:00 committed by GitHub
parent 3aab526a43
commit 33310a43c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 5268 additions and 666 deletions

View File

@ -29,5 +29,5 @@ jobs:
with:
node-version-file: './.tool-versions'
- name: Lint
run: npm install && npm run test:lint:eslint
run: npm install && npm run lint
working-directory: ./backend

View File

@ -31,5 +31,5 @@ jobs:
- name: Install Dependencies & Build Library
run: |
npm install
npm run test:unit
npm test
working-directory: ./backend

1
.gitignore vendored
View File

@ -3,4 +3,5 @@
/docs/.vuepress/dist/
/docs/.vuepress/.cache/
/docs/.vuepress/.temp/
/docs/.vuepress/*.mjs
/.github/webhooks/hooks.json

View File

@ -1,14 +0,0 @@
{
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": false,
"singleQuote": true,
"quoteProps": "as-needed",
"jsxSingleQuote": true,
"trailingComma": "all",
"bracketSpacing": true,
"bracketSameLine": false,
"arrowParens": "always",
"endOfLine": "auto"
}

View File

@ -7,8 +7,10 @@ export default [
{
languageOptions: {
parserOptions: {
projectService: false,
project: './tsconfig.eslint.json',
projectService: {
allowDefaultProject: ['jest/*.ts', 'src/*.spec.ts', 'src/*.test.ts'],
defaultProject: './tsconfig.eslint.json',
},
},
},
},

View File

@ -18,7 +18,7 @@
"devDependencies": {
"@jest/globals": "^30.2.0",
"eslint": "^9.39.2",
"eslint-config-it4c": "^0.10.0",
"eslint-config-it4c": "^0.11.2",
"jest": "^30.2.0",
"ts-jest": "^29.4.6",
"tsx": "^4.21.0",
@ -1204,6 +1204,62 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/css": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@eslint/css/-/css-0.7.0.tgz",
"integrity": "sha512-d6mo8etv4igrTGxgvWSgA5+TsppfObM/Xhlu8JWbkqNBiaJXztUNH45R1B4i1GL2PNIFMLREI3Kh9lTBi19l7g==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@eslint/core": "^0.13.0",
"@eslint/css-tree": "^3.3.3",
"@eslint/plugin-kit": "^0.2.5"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/css-tree": {
"version": "3.6.9",
"resolved": "https://registry.npmjs.org/@eslint/css-tree/-/css-tree-3.6.9.tgz",
"integrity": "sha512-3D5/OHibNEGk+wKwNwMbz63NMf367EoR4mVNNpxddCHKEb2Nez7z62J2U6YjtErSsZDoY0CsccmoUpdEbkogNA==",
"dev": true,
"license": "MIT",
"dependencies": {
"mdn-data": "2.23.0",
"source-map-js": "^1.0.1"
},
"engines": {
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
}
},
"node_modules/@eslint/css/node_modules/@eslint/core": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz",
"integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@types/json-schema": "^7.0.15"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/css/node_modules/@eslint/plugin-kit": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz",
"integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@eslint/core": "^0.13.0",
"levn": "^0.4.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/eslintrc": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
@ -3114,17 +3170,56 @@
"dev": true,
"license": "MIT"
},
"node_modules/@typescript-eslint/parser": {
"version": "8.54.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz",
"integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==",
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.55.0.tgz",
"integrity": "sha512-1y/MVSz0NglV1ijHC8OT49mPJ4qhPYjiK08YUQVbIOyu+5k862LKUHFkpKHWu//zmr7hDR2rhwUm6gnCGNmGBQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/scope-manager": "8.54.0",
"@typescript-eslint/types": "8.54.0",
"@typescript-eslint/typescript-estree": "8.54.0",
"@typescript-eslint/visitor-keys": "8.54.0",
"@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.55.0",
"@typescript-eslint/type-utils": "8.55.0",
"@typescript-eslint/utils": "8.55.0",
"@typescript-eslint/visitor-keys": "8.55.0",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.4.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.55.0",
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.55.0.tgz",
"integrity": "sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/scope-manager": "8.55.0",
"@typescript-eslint/types": "8.55.0",
"@typescript-eslint/typescript-estree": "8.55.0",
"@typescript-eslint/visitor-keys": "8.55.0",
"debug": "^4.4.3"
},
"engines": {
@ -3140,14 +3235,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.54.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz",
"integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==",
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.55.0.tgz",
"integrity": "sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.54.0",
"@typescript-eslint/types": "^8.54.0",
"@typescript-eslint/tsconfig-utils": "^8.55.0",
"@typescript-eslint/types": "^8.55.0",
"debug": "^4.4.3"
},
"engines": {
@ -3162,14 +3257,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.54.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz",
"integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==",
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.55.0.tgz",
"integrity": "sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.54.0",
"@typescript-eslint/visitor-keys": "8.54.0"
"@typescript-eslint/types": "8.55.0",
"@typescript-eslint/visitor-keys": "8.55.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -3180,9 +3275,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.54.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz",
"integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==",
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.55.0.tgz",
"integrity": "sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q==",
"dev": true,
"license": "MIT",
"engines": {
@ -3196,10 +3291,35 @@
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.55.0.tgz",
"integrity": "sha512-x1iH2unH4qAt6I37I2CGlsNs+B9WGxurP2uyZLRz6UJoZWDBx9cJL1xVN/FiOmHEONEg6RIufdvyT0TEYIgC5g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.55.0",
"@typescript-eslint/typescript-estree": "8.55.0",
"@typescript-eslint/utils": "8.55.0",
"debug": "^4.4.3",
"ts-api-utils": "^2.4.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.54.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz",
"integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==",
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.55.0.tgz",
"integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==",
"dev": true,
"license": "MIT",
"engines": {
@ -3211,16 +3331,16 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.54.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz",
"integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==",
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.55.0.tgz",
"integrity": "sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.54.0",
"@typescript-eslint/tsconfig-utils": "8.54.0",
"@typescript-eslint/types": "8.54.0",
"@typescript-eslint/visitor-keys": "8.54.0",
"@typescript-eslint/project-service": "8.55.0",
"@typescript-eslint/tsconfig-utils": "8.55.0",
"@typescript-eslint/types": "8.55.0",
"@typescript-eslint/visitor-keys": "8.55.0",
"debug": "^4.4.3",
"minimatch": "^9.0.5",
"semver": "^7.7.3",
@ -3265,16 +3385,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.54.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz",
"integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==",
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.55.0.tgz",
"integrity": "sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/scope-manager": "8.54.0",
"@typescript-eslint/types": "8.54.0",
"@typescript-eslint/typescript-estree": "8.54.0"
"@typescript-eslint/scope-manager": "8.55.0",
"@typescript-eslint/types": "8.55.0",
"@typescript-eslint/typescript-estree": "8.55.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -3289,13 +3409,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.54.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz",
"integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==",
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.55.0.tgz",
"integrity": "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.54.0",
"@typescript-eslint/types": "8.55.0",
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
@ -3622,186 +3742,6 @@
}
}
},
"node_modules/@vitest/eslint-plugin/node_modules/@typescript-eslint/project-service": {
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.55.0.tgz",
"integrity": "sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.55.0",
"@typescript-eslint/types": "^8.55.0",
"debug": "^4.4.3"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@vitest/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.55.0.tgz",
"integrity": "sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.55.0",
"@typescript-eslint/visitor-keys": "8.55.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@vitest/eslint-plugin/node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.55.0.tgz",
"integrity": "sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@vitest/eslint-plugin/node_modules/@typescript-eslint/types": {
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.55.0.tgz",
"integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@vitest/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": {
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.55.0.tgz",
"integrity": "sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.55.0",
"@typescript-eslint/tsconfig-utils": "8.55.0",
"@typescript-eslint/types": "8.55.0",
"@typescript-eslint/visitor-keys": "8.55.0",
"debug": "^4.4.3",
"minimatch": "^9.0.5",
"semver": "^7.7.3",
"tinyglobby": "^0.2.15",
"ts-api-utils": "^2.4.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@vitest/eslint-plugin/node_modules/@typescript-eslint/utils": {
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.55.0.tgz",
"integrity": "sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/scope-manager": "8.55.0",
"@typescript-eslint/types": "8.55.0",
"@typescript-eslint/typescript-estree": "8.55.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@vitest/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.55.0.tgz",
"integrity": "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.55.0",
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@vitest/eslint-plugin/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@vitest/eslint-plugin/node_modules/eslint-visitor-keys": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/@vitest/eslint-plugin/node_modules/minimatch": {
"version": "9.0.5",
"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"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@vue/eslint-config-typescript": {
"version": "14.6.0",
"resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-14.6.0.tgz",
@ -5347,12 +5287,13 @@
}
},
"node_modules/eslint-config-it4c": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/eslint-config-it4c/-/eslint-config-it4c-0.10.0.tgz",
"integrity": "sha512-YoLjkhaFlqQ3IWnfM4FaZcE57xCcb1zqEwadxSKQL7M6Fbn9nk/5md94fDTz3X4FyIrEyxJddyFy9CgAWwIyMA==",
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/eslint-config-it4c/-/eslint-config-it4c-0.11.2.tgz",
"integrity": "sha512-2ZiGvcjQAQPUbvLns83WGvnFlVupsVFJF9erCFYbR2ktKDvkTxqBxQEh6b4d4CDOhIBqAabkphtBkmdOF6SYCw==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "^4.6.0",
"@eslint/css": "^0.7.0",
"@eslint/js": "^9.39.2",
"@graphql-eslint/eslint-plugin": "^4.4.0",
"@vitest/eslint-plugin": "^1.6.7",
@ -5365,10 +5306,10 @@
"eslint-plugin-no-catch-all": "^1.1.0",
"eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-security": "^3.0.1",
"eslint-plugin-vue": "^10.7.0",
"eslint-plugin-yml": "^3.0.0",
"eslint-plugin-vue": "^10.8.0",
"eslint-plugin-yml": "^3.1.2",
"neostandard": "^0.12.2",
"typescript-eslint": "^8.54.0"
"typescript-eslint": "^8.55.0"
},
"peerDependencies": {
"eslint": ">= 9"
@ -5739,9 +5680,9 @@
}
},
"node_modules/eslint-plugin-vue": {
"version": "10.7.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.7.0.tgz",
"integrity": "sha512-r2XFCK4qlo1sxEoAMIoTTX0PZAdla0JJDt1fmYiworZUX67WeEGqm+JbyAg3M+pGiJ5U6Mp5WQbontXWtIW7TA==",
"version": "10.8.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.8.0.tgz",
"integrity": "sha512-f1J/tcbnrpgC8suPN5AtdJ5MQjuXbSU9pGRSSYAuF3SHoiYCOdEX6O22pLaRyLHXvDcOe+O5ENgc1owQ587agA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -5758,7 +5699,7 @@
"peerDependencies": {
"@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0",
"@typescript-eslint/parser": "^7.0.0 || ^8.0.0",
"eslint": "^8.57.0 || ^9.0.0",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"vue-eslint-parser": "^10.0.0"
},
"peerDependenciesMeta": {
@ -5771,14 +5712,14 @@
}
},
"node_modules/eslint-plugin-yml": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-3.0.0.tgz",
"integrity": "sha512-kuAW6o3hlFHyF5p7TLon+AtvNWnsvRrb88pqywGMSCEqAP5d1gOMvNGgWLVlKHqmx5RbFhQLcxFDGmS4IU9DwA==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-3.1.2.tgz",
"integrity": "sha512-n9lxbFrNlGDLOSyIrEYkkYr7icbULMh66wwkIEluisq0lXSu1qVEEXM0g8MM8UQbtd9t1HMgN6bC+DaOe5dWdQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint/core": "^1.0.1",
"@eslint/plugin-kit": "^0.5.1",
"@eslint/plugin-kit": "^0.6.0",
"debug": "^4.3.2",
"diff-sequences": "^29.0.0",
"escape-string-regexp": "5.0.0",
@ -5809,13 +5750,13 @@
}
},
"node_modules/eslint-plugin-yml/node_modules/@eslint/plugin-kit": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.5.1.tgz",
"integrity": "sha512-hZ2uC1jbf6JMSsF2ZklhRQqf6GLpYyux6DlzegnW/aFlpu6qJj5GO7ub7WOETCrEl6pl6DAX7RgTgj/fyG+6BQ==",
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.0.tgz",
"integrity": "sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@eslint/core": "^1.0.1",
"@eslint/core": "^1.1.0",
"levn": "^0.4.1"
},
"engines": {
@ -8627,6 +8568,13 @@
"node": ">= 0.4"
}
},
"node_modules/mdn-data": {
"version": "2.23.0",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.23.0.tgz",
"integrity": "sha512-786vq1+4079JSeu2XdcDjrhi/Ry7BWtjDl9WtGPWLiIHb2T66GvIVflZTBoSNZ5JqTtJGYEVMuFA/lbQlMOyDQ==",
"dev": true,
"license": "CC0-1.0"
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@ -10152,6 +10100,16 @@
"node": ">=0.10.0"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.13",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
@ -10899,16 +10857,16 @@
}
},
"node_modules/typescript-eslint": {
"version": "8.54.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.54.0.tgz",
"integrity": "sha512-CKsJ+g53QpsNPqbzUsfKVgd3Lny4yKZ1pP4qN3jdMOg/sisIDLGyDMezycquXLE5JsEU0wp3dGNdzig0/fmSVQ==",
"version": "8.55.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.55.0.tgz",
"integrity": "sha512-HE4wj+r5lmDVS9gdaN0/+iqNvPZwGfnJ5lZuz7s5vLlg9ODw0bIiiETaios9LvFI1U94/VBXGm3CB2Y5cNFMpw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.54.0",
"@typescript-eslint/parser": "8.54.0",
"@typescript-eslint/typescript-estree": "8.54.0",
"@typescript-eslint/utils": "8.54.0"
"@typescript-eslint/eslint-plugin": "8.55.0",
"@typescript-eslint/parser": "8.55.0",
"@typescript-eslint/typescript-estree": "8.55.0",
"@typescript-eslint/utils": "8.55.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -10922,70 +10880,6 @@
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.54.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz",
"integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.54.0",
"@typescript-eslint/type-utils": "8.54.0",
"@typescript-eslint/utils": "8.54.0",
"@typescript-eslint/visitor-keys": "8.54.0",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.4.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.54.0",
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": {
"version": "8.54.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz",
"integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.54.0",
"@typescript-eslint/typescript-estree": "8.54.0",
"@typescript-eslint/utils": "8.54.0",
"debug": "^4.4.3",
"ts-api-utils": "^2.4.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/typescript-eslint/node_modules/ignore": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/uglify-js": {
"version": "3.19.3",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",

View File

@ -4,7 +4,7 @@
"description": "IT4C.dev backend",
"license": "Apache-2.0",
"author": "Ulf Gebhardt",
"type": "commonjs",
"type": "module",
"main": "index.js",
"repository": {
"type": "git",
@ -14,14 +14,14 @@
"start": "node ./build/src/index.js",
"build": "tsc",
"dev": "tsx watch ./src/index.ts",
"test:unit": "NODE_OPTIONS='--experimental-vm-modules' jest",
"test:lint:eslint": "eslint --max-warnings 0 .",
"test": "NODE_OPTIONS='--experimental-vm-modules' jest",
"lint": "eslint --max-warnings 0 .",
"update": "npx npm-check-updates"
},
"devDependencies": {
"@jest/globals": "^30.2.0",
"eslint": "^9.39.2",
"eslint-config-it4c": "^0.10.0",
"eslint-config-it4c": "^0.11.2",
"jest": "^30.2.0",
"ts-jest": "^29.4.6",
"tsx": "^4.21.0",

View File

@ -26,7 +26,7 @@ function createServer(env: Env): FastifyInstance {
// Fatify
const fastify = Fastify({
logger: true,
logger: env.NODE_ENV !== 'test',
}).setValidatorCompiler(TypeBoxValidatorCompiler)
// Mail

View File

@ -11,7 +11,7 @@
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"target": "ES2022" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
@ -25,9 +25,9 @@
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */
"module": "NodeNext" /* Specify what module code is generated. */,
"module": "ESNext" /* Specify what module code is generated. */,
// "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "nodenext" /* Specify how TypeScript looks up a file from a given module specifier. */,
"moduleResolution": "Bundler" /* Specify how TypeScript looks up a file from a given module specifier. */,
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
"paths": {
/* Specify a set of entries that re-map imports to additional lookup locations. */

View File

@ -1,14 +1,15 @@
import { defineClientConfig } from 'vuepress/client'
import { setupTransparentNavbar } from 'vuepress-theme-hope/presets/transparentNavbar.js'
import BlankLayout from './layouts/BlankLayout.vue'
import CaptionedImage from './components/CaptionedImage.vue'
import ContactForm from './components/ContactForm.vue'
import ContentSection from './components/ContentSection.vue'
import VPFooter from './components/VPFooter.vue'
import ProcessStep from './components/ProcessStep.vue'
import ProjectCard from './components/ProjectCard.vue'
import ServiceCard from './components/ServiceCard.vue'
import TeamMember from './components/TeamMember.vue'
import CaptionedImage from './components/CaptionedImage.vue'
import VPFooter from './components/VPFooter.vue'
import BlankLayout from './layouts/BlankLayout.vue'
export default defineClientConfig({
enhance({ app }) {
@ -24,9 +25,8 @@ export default defineClientConfig({
setup() {
setupTransparentNavbar({ type: 'homepage' })
},
// You can override or add layouts here
layouts: {
// For example, here we change the default layout of vuepress-theme-hope to layouts/Layout.vue
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
BlankLayout,
},
})

View File

@ -6,15 +6,15 @@
</template>
<script setup lang="ts">
defineProps<{
src: string
caption: string
width: string
}>()
defineProps<{
src: string
caption: string
width: string
}>()
</script>
<style lang="scss">
figcaption {
font-style: italic;
}
figcaption {
font-style: italic;
}
</style>

View File

@ -109,76 +109,79 @@
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import { reactive, ref } from 'vue'
const form = reactive({
name: '',
email: '',
phone: '',
message: '',
})
const form = reactive({
name: '',
email: '',
phone: '',
message: '',
})
const isSubmitting = ref(false)
const submitSuccess = ref(false)
const submitError = ref('')
const isSubmitting = ref(false)
const submitSuccess = ref(false)
const submitError = ref('')
const handleSubmit = async () => {
try {
isSubmitting.value = true
submitError.value = ''
const handleSubmit = async () => {
try {
isSubmitting.value = true
submitError.value = ''
const response = await fetch('/api/mail', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: form.name,
email: form.email,
telephone: form.phone || undefined, // Send undefined if empty to match optional schema
text: form.message,
}),
})
const response = await fetch('/api/mail', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: form.name,
email: form.email,
telephone: form.phone || undefined, // Send undefined if empty to match optional schema
text: form.message,
}),
})
if (response.status !== 200) {
throw new Error('Bei der Kommunikation mit dem Server ist ein Fehler aufgetreten.')
if (response.status !== 200) {
throw new Error('Bei der Kommunikation mit dem Server ist ein Fehler aufgetreten.')
}
const result = await response.json()
if (!response.ok) {
throw new Error(result.error || 'Fehler beim Senden der Nachricht')
}
// Clear form on success
form.name = ''
form.email = ''
form.phone = ''
form.message = ''
submitSuccess.value = true
setTimeout(() => {
submitSuccess.value = false
}, 5000) // Hide success message after 5 seconds
} catch (error: unknown) {
if (error instanceof Error) {
submitError.value = error.message
} else {
throw error
}
} finally {
isSubmitting.value = false
}
const result = await response.json()
if (!response.ok) {
throw new Error(result.error || 'Fehler beim Senden der Nachricht')
}
// Clear form on success
form.name = ''
form.email = ''
form.phone = ''
form.message = ''
submitSuccess.value = true
setTimeout(() => {
submitSuccess.value = false
}, 5000) // Hide success message after 5 seconds
} catch (error) {
submitError.value =
error instanceof Error ? error.message : 'Ein unbekannter Fehler ist aufgetreten'
} finally {
isSubmitting.value = false
}
}
</script>
<style>
.phone-number {
color: var(--highlight-color);
}
.focus\:highlight:focus {
--tw-ring-color: var(--highlight-color);
}
button {
background-color: var(--highlight-color);
&:hover {
background-color: color-mix(in srgb, var(--highlight-color), black 15%);
.phone-number {
color: var(--highlight-color);
}
.focus\:highlight:focus {
--tw-ring-color: var(--highlight-color);
}
button {
background-color: var(--highlight-color);
&:hover {
background-color: color-mix(in srgb, var(--highlight-color), black 15%);
}
}
}
</style>

View File

@ -9,22 +9,22 @@
</section>
</template>
<script>
export default {
name: 'ContentSection',
props: {
title: {
type: String,
required: true,
<script lang="ts">
export default {
name: 'ContentSection',
props: {
title: {
type: String,
required: true,
},
backgroundColor: {
type: String,
default: 'bg-white dark:bg-gray-900',
},
id: {
type: String,
default: '',
},
},
backgroundColor: {
type: String,
default: 'bg-white dark:bg-gray-900',
},
id: {
type: String,
default: '',
},
},
}
}
</script>

View File

@ -6,22 +6,26 @@
}}</span>
</div>
<div class="col-span-9 pt-0 sm:pt-2">
<h3 class="text-xl font-semibold mb-2">{{ title }}</h3>
<p class="text-gray-600 dark:text-gray-300">{{ description }}</p>
<h3 class="text-xl font-semibold mb-2">
{{ title }}
</h3>
<p class="text-gray-600 dark:text-gray-300">
{{ description }}
</p>
</div>
</div>
</template>
<script setup lang="ts">
defineProps<{
number: string
title: string
description: string
}>()
defineProps<{
number: string
title: string
description: string
}>()
</script>
<style>
.highlight-number {
color: var(--highlight-color);
}
.highlight-number {
color: var(--highlight-color);
}
</style>

View File

@ -14,19 +14,19 @@
</template>
<script setup lang="ts">
defineProps<{
title: string
description: string
image: string
tags: string[]
href: string
target?: string
}>()
defineProps<{
title: string
description: string
image: string
tags: string[]
href: string
target?: string
}>()
</script>
<style>
.tag {
color: var(--highlight-color);
background: var(--highlight-color-light);
}
.tag {
color: var(--highlight-color);
background: var(--highlight-color-light);
}
</style>

View File

@ -1,15 +1,19 @@
<template>
<div class="p-6 border border-gray-300 rounded-lg">
<h3 class="text-xl font-semibold mb-4">{{ title }}</h3>
<h3 class="text-xl font-semibold mb-4">
{{ title }}
</h3>
<ul class="space-y-2 text-gray-600 dark:text-gray-300">
<li v-for="item in items" :key="item">{{ item }}</li>
<li v-for="item in items" :key="item">
{{ item }}
</li>
</ul>
</div>
</template>
<script setup lang="ts">
defineProps<{
title: string
items: string[]
}>()
defineProps<{
title: string
items: string[]
}>()
</script>

View File

@ -13,7 +13,7 @@
<!-- Overlay mit highlight-color-light Variable -->
<div
class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[115%] h-[115%] rounded-full overlay-bg opacity-0 group-hover:opacity-25 transition-opacity duration-200"
></div>
/>
</div>
<h4
@ -26,16 +26,16 @@
</template>
<script setup lang="ts">
defineProps<{
name: string
role: string
image: string
profileUrl: string
}>()
defineProps<{
name: string
role: string
image: string
profileUrl: string
}>()
</script>
<style>
.overlay-bg {
background-color: var(--highlight-color-light);
}
.overlay-bg {
background-color: var(--highlight-color-light);
}
</style>

View File

@ -43,13 +43,13 @@
</footer>
</template>
<script>
export default {
name: 'FooterSection',
computed: {
currentYear() {
return new Date().getFullYear()
<script lang="ts">
export default {
name: 'FooterSection',
computed: {
currentYear() {
return new Date().getFullYear()
},
},
},
}
}
</script>

View File

@ -1,9 +1,10 @@
import tailwindcss from '@tailwindcss/vite'
import { viteBundler } from '@vuepress/bundler-vite'
import Imagemin from 'vuepress-plugin-imagemin'
import { defineUserConfig } from 'vuepress'
import Imagemin from 'vuepress-plugin-imagemin'
import meta from './config/meta'
import theme from './config/theme'
import tailwindcss from '@tailwindcss/vite'
export default defineUserConfig({
lang: 'de-DE',

View File

@ -1,4 +1,4 @@
import { HeadConfig } from 'vuepress'
import type { HeadConfig } from 'vuepress'
export default {
title: 'IT4C',

View File

@ -5,128 +5,128 @@
</div>
</template>
<script>
export default {
name: 'BlankLayout',
}
<script lang="ts">
export default {
name: 'BlankLayout',
}
</script>
<style>
@layer theme, base, components, utilities;
@layer theme, base, components, utilities;
@import 'tailwindcss/theme.css' layer(theme);
@import 'tailwindcss/preflight.css' layer(base);
@import 'tailwindcss/utilities.css' layer(utilities);
@import 'tailwindcss/theme.css' layer(theme);
@import 'tailwindcss/preflight.css' layer(base);
@import 'tailwindcss/utilities.css' layer(utilities);
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
/* Conflicts with vuepress */
@layer base {
.vp-sidebar {
box-sizing: content-box;
}
.vp-nav-logo {
display: inline;
}
.theme-hope-content p {
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
}
.theme-hope-content ul {
list-style: unset;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
}
.theme-hope-content figure {
margin: inherit;
padding: inherit;
}
}
.blank-layout {
--content-width: 1160px;
}
.blank-layout h1,
.blank-layout h2,
.blank-layout h3,
.blank-layout h4,
.blank-layout h5,
.blank-layout h6 {
font-family: var(--font-family-heading);
}
.blank-layout h1,
.blank-layout h2 {
border-bottom: none;
padding-bottom: 2rem;
font-weight: bold;
}
.blank-layout .content-width {
max-width: var(--content-width);
margin: 0 auto;
padding: 0 2.5rem;
@media (max-width: 768px) {
padding: 0 1.75rem;
}
@media (max-width: 400px) {
padding: 0 1rem;
}
}
/* iOS Safari specific global fixes */
@supports (-webkit-touch-callout: none) {
html {
/* Fix for iOS Safari viewport height issues */
height: -webkit-fill-available;
/* Conflicts with vuepress */
@layer base {
.vp-sidebar {
box-sizing: content-box;
}
.vp-nav-logo {
display: inline;
}
.theme-hope-content p {
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
}
.theme-hope-content ul {
list-style: unset;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
}
.theme-hope-content figure {
margin: inherit;
padding: inherit;
}
}
body {
/* Fix for iOS Safari bounce scrolling */
-webkit-overflow-scrolling: touch;
/* Prevent zoom on input focus */
-webkit-text-size-adjust: 100%;
/* Fix for iOS Safari height issues */
min-height: -webkit-fill-available;
.blank-layout {
--content-width: 1160px;
}
/* Fix for iOS Safari input zoom */
input,
textarea,
select {
font-size: 16px !important;
-webkit-appearance: none;
border-radius: 0;
.blank-layout h1,
.blank-layout h2,
.blank-layout h3,
.blank-layout h4,
.blank-layout h5,
.blank-layout h6 {
font-family: var(--font-family-heading);
}
/* Fix for iOS Safari button styling */
button,
.hero-button {
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent;
border-radius: 0;
}
}
/* Additional responsive fixes for older iOS versions */
@media screen and (max-width: 768px) {
/* Fix for older iOS Safari transform issues */
.hero-section img {
-webkit-transform: translateZ(0);
transform: translateZ(0);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
.blank-layout h1,
.blank-layout h2 {
border-bottom: none;
padding-bottom: 2rem;
font-weight: bold;
}
/* Prevent horizontal scrolling on older iOS */
body {
overflow-x: hidden;
.blank-layout .content-width {
max-width: var(--content-width);
margin: 0 auto;
padding: 0 2.5rem;
@media (max-width: 768px) {
padding: 0 1.75rem;
}
@media (max-width: 400px) {
padding: 0 1rem;
}
}
/* iOS Safari specific global fixes */
@supports (-webkit-touch-callout: none) {
html {
/* Fix for iOS Safari viewport height issues */
height: -webkit-fill-available;
}
body {
/* Fix for iOS Safari bounce scrolling */
-webkit-overflow-scrolling: touch;
/* Prevent zoom on input focus */
-webkit-text-size-adjust: 100%;
/* Fix for iOS Safari height issues */
min-height: -webkit-fill-available;
}
/* Fix for iOS Safari input zoom */
input,
textarea,
select {
font-size: 16px !important;
-webkit-appearance: none;
border-radius: 0;
}
/* Fix for iOS Safari button styling */
button,
.hero-button {
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent;
border-radius: 0;
}
}
/* Additional responsive fixes for older iOS versions */
@media screen and (max-width: 768px) {
/* Fix for older iOS Safari transform issues */
.hero-section img {
-webkit-transform: translateZ(0);
transform: translateZ(0);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
/* Prevent horizontal scrolling on older iOS */
body {
overflow-x: hidden;
}
}
}
</style>

View File

@ -1,10 +1,6 @@
import eslint from '@eslint/js'
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
import eslintPluginVue from 'eslint-plugin-vue'
import globals from 'globals'
import typescriptEslint from 'typescript-eslint'
import config, { vue3 } from 'eslint-config-it4c'
export default typescriptEslint.config(
export default [
{
ignores: [
'coverage',
@ -12,26 +8,28 @@ export default typescriptEslint.config(
'docs/.vuepress/.cache',
'docs/.vuepress/.temp',
'docs/.vuepress/dist',
'docs/.vuepress/*.mjs',
],
},
...config,
...vue3,
{
files: ['**/*.cjs'],
rules: {
'import-x/no-commonjs': 'off',
},
},
{
extends: [
eslint.configs.recommended,
...typescriptEslint.configs.recommended,
...eslintPluginVue.configs['flat/recommended'],
],
files: ['**/*.{ts,vue}'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: globals.browser,
parserOptions: {
parser: typescriptEslint.parser,
},
},
rules: {
// your rules
'n/no-unpublished-import': 'off',
'import-x/no-extraneous-dependencies': 'off',
},
},
eslintPluginPrettierRecommended,
)
{
files: ['**/*.vue'],
rules: {
'vue/html-self-closing': ['error', { html: { void: 'any' } }],
'vue/singleline-html-element-content-newline': 'off',
},
},
]

4793
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,13 +2,14 @@
"name": "it4c.dev",
"version": "1.0.0",
"description": "The IT4C.dev website",
"type": "module",
"main": "index.js",
"scripts": {
"build": "vuepress build docs",
"dev": "vuepress dev docs",
"dev-prod": "npm run build && http-server ./docs/.vuepress/dist",
"test": "npm run test:lint:textlint && npm run test:lint:eslint",
"test:lint:eslint": "eslint",
"test:lint:eslint": "eslint --max-warnings 0 .",
"test:lint:textlint": "textlint \"*.md\" \"docs/**/*.md\""
},
"repository": {
@ -27,12 +28,8 @@
"@vuepress/bundler-vite": "^2.0.0-rc.26",
"@vuepress/plugin-slimsearch": "^2.0.0-rc.121",
"eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-vue": "^10.8.0",
"globals": "^17.3.0",
"eslint-config-it4c": "^0.11.2",
"http-server": "^14.1.1",
"prettier": "3.8.1",
"sass-embedded": "^1.97.3",
"tailwindcss": "^4.1.17",
"textlint": "^15.5.1",
@ -49,7 +46,6 @@
"textlint-rule-no-zero-width-spaces": "^1.0.1",
"textlint-rule-period-in-list-item": "^1.0.1",
"textlint-rule-write-good": "^2.0.0",
"typescript-eslint": "^8.55.0",
"vuepress": "^2.0.0-rc.26",
"vuepress-plugin-imagemin": "^0.1.2",
"vuepress-theme-hope": "^2.0.0-rc.102"

3
prettier.config.ts Normal file
View File

@ -0,0 +1,3 @@
import config from 'eslint-config-it4c/prettier'
export default config

View File

@ -1,4 +1,4 @@
module.exports = {
export default {
content: ['./docs/**/*.{vue,js,ts,jsx,tsx,md}', '!./**/cache', '!./**/.temp'],
theme: {
extend: {},

15
tsconfig.json Normal file
View File

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"jsx": "preserve",
"skipLibCheck": true,
"esModuleInterop": true,
"allowImportingTsExtensions": true,
"noEmit": true
},
"include": ["*.ts", "docs/.vuepress/**/*.ts", "docs/.vuepress/**/*.vue"],
"exclude": ["node_modules", "backend"]
}