From 061376402bb9c20de9e629b63338e61324a0a066 Mon Sep 17 00:00:00 2001 From: danielvici123 Date: Wed, 19 Nov 2025 19:14:40 +0100 Subject: [PATCH] files formatted; add: qrcode generator --- .prettierrc.json | 7 + package-lock.json | 314 +++++++++++++++++- package.json | 5 +- src/app/app.html | 4 +- src/app/app.routes.ts | 15 +- .../components/custom-card/custom-card.html | 8 +- src/app/components/custom-card/custom-card.ts | 5 +- .../custom-description.html | 4 +- .../custom-description.spec.ts | 5 +- .../custom-description/custom-description.ts | 4 +- .../components/custom-title/custom-title.html | 10 +- .../components/custom-title/custom-title.ts | 4 +- .../generator-password.component.html | 99 ++++-- .../generator-password.component.spec.ts | 5 +- .../password/generator-password.component.ts | 38 +-- .../generator/qrcode/generator-qrcode.css | 0 .../generator/qrcode/generator-qrcode.html | 64 ++++ .../generator/qrcode/generator-qrcode.spec.ts | 22 ++ .../generator/qrcode/generator-qrcode.ts | 61 ++++ src/app/sites/startpage/startpage.html | 8 +- src/app/sites/startpage/startpage.ts | 65 ++-- src/app/sites/test-it/test-it.html | 4 +- src/app/sites/test-it/test-it.spec.ts | 5 +- src/app/sites/test-it/test-it.ts | 10 +- src/index.html | 2 +- 25 files changed, 627 insertions(+), 141 deletions(-) create mode 100644 .prettierrc.json create mode 100644 src/app/sites/generator/qrcode/generator-qrcode.css create mode 100644 src/app/sites/generator/qrcode/generator-qrcode.html create mode 100644 src/app/sites/generator/qrcode/generator-qrcode.spec.ts create mode 100644 src/app/sites/generator/qrcode/generator-qrcode.ts diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..2abf692 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,7 @@ +{ + "singleQuote": true, + "trailingComma": "es5", + "printWidth": 80, + "tabWidth": 2, + "semi": true +} diff --git a/package-lock.json b/package-lock.json index 533aca3..aebb1e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,8 +15,9 @@ "@angular/platform-browser": "^20.3.0", "@angular/router": "^20.3.0", "@tailwindcss/postcss": "^4.1.17", + "@vercel/speed-insights": "^1.2.0", "postcss": "^8.5.6", - "prettier": "^3.6.2", + "qrcode": "^1.5.4", "rxjs": "~7.8.0", "tailwindcss": "^4.1.17", "tslib": "^2.3.0", @@ -27,12 +28,14 @@ "@angular/cli": "^20.3.1", "@angular/compiler-cli": "^20.3.0", "@types/jasmine": "~5.1.0", + "@types/qrcode": "^1.5.6", "jasmine-core": "~5.9.0", "karma": "~6.4.0", "karma-chrome-launcher": "~3.2.0", "karma-coverage": "~2.2.0", "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.1.0", + "prettier": "^3.6.2", "typescript": "~5.9.2" } }, @@ -2576,9 +2579,9 @@ } }, "node_modules/@npmcli/package-json/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -3829,6 +3832,51 @@ "undici-types": "~7.16.0" } }, + "node_modules/@types/qrcode": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.6.tgz", + "integrity": "sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@vercel/speed-insights": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@vercel/speed-insights/-/speed-insights-1.2.0.tgz", + "integrity": "sha512-y9GVzrUJ2xmgtQlzFP2KhVRoCglwfRQgjyfY607aU0hh0Un6d0OUyrJkjuAlsV18qR4zfoFPs/BiIj9YDS6Wzw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "peerDependencies": { + "@sveltejs/kit": "^1 || ^2", + "next": ">= 13", + "react": "^18 || ^19 || ^19.0.0-rc", + "svelte": ">= 4", + "vue": "^3", + "vue-router": "^4" + }, + "peerDependenciesMeta": { + "@sveltejs/kit": { + "optional": true + }, + "next": { + "optional": true + }, + "react": { + "optional": true + }, + "svelte": { + "optional": true + }, + "vue": { + "optional": true + }, + "vue-router": { + "optional": true + } + } + }, "node_modules/@vitejs/plugin-basic-ssl": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.1.0.tgz", @@ -4234,9 +4282,9 @@ } }, "node_modules/cacache/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -4335,6 +4383,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001754", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", @@ -4495,7 +4552,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -4508,7 +4564,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/colorette": { @@ -4754,6 +4809,15 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -4791,6 +4855,12 @@ "dev": true, "license": "MIT" }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", + "license": "MIT" + }, "node_modules/dom-serialize": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", @@ -5394,6 +5464,19 @@ "node": ">= 0.8" } }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/flatted": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", @@ -5533,7 +5616,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -7080,6 +7162,18 @@ "@lmdb/lmdb-win32-x64": "3.4.2" } }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -8089,6 +8183,33 @@ "license": "MIT", "optional": true }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/p-map": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", @@ -8102,6 +8223,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -8254,6 +8384,15 @@ "node": ">= 0.8" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -8358,6 +8497,15 @@ "node": ">=16.20.0" } }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -8397,6 +8545,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" @@ -8463,6 +8612,125 @@ "node": ">=0.9" } }, + "node_modules/qrcode": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", + "license": "MIT", + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qrcode/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/qrcode/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/qrcode/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/qrcode/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", @@ -8530,7 +8798,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8546,6 +8813,12 @@ "node": ">=0.10.0" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -8812,6 +9085,12 @@ "node": ">= 18" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -9951,11 +10230,16 @@ "node": ">= 8" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, "node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -10060,7 +10344,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10070,7 +10353,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -10086,14 +10368,12 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10103,7 +10383,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -10118,7 +10397,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" diff --git a/package.json b/package.json index f6993a7..0c62d4a 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,9 @@ "@angular/platform-browser": "^20.3.0", "@angular/router": "^20.3.0", "@tailwindcss/postcss": "^4.1.17", + "@vercel/speed-insights": "^1.2.0", "postcss": "^8.5.6", - "prettier": "^3.6.2", + "qrcode": "^1.5.4", "rxjs": "~7.8.0", "tailwindcss": "^4.1.17", "tslib": "^2.3.0", @@ -41,12 +42,14 @@ "@angular/cli": "^20.3.1", "@angular/compiler-cli": "^20.3.0", "@types/jasmine": "~5.1.0", + "@types/qrcode": "^1.5.6", "jasmine-core": "~5.9.0", "karma": "~6.4.0", "karma-chrome-launcher": "~3.2.0", "karma-coverage": "~2.2.0", "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.1.0", + "prettier": "^3.6.2", "typescript": "~5.9.2" } } diff --git a/src/app/app.html b/src/app/app.html index 3348174..46622c6 100644 --- a/src/app/app.html +++ b/src/app/app.html @@ -1,6 +1,6 @@ -
- +
+
diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index d467bf0..752d2e1 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,23 +1,28 @@ import { Routes } from '@angular/router'; import { Startpage } from './sites/startpage/startpage'; -import {TestIt} from './sites/test-it/test-it'; -import {GeneratorPassword} from './sites/generator/password/generator-password.component'; +import { TestIt } from './sites/test-it/test-it'; +import { GeneratorPassword } from './sites/generator/password/generator-password.component'; +import { GeneratorQrcode } from './sites/generator/qrcode/generator-qrcode'; export const routes: Routes = [ { - path:'test', + path: 'test', component: TestIt, }, { path: '', component: Startpage, - }, + }, // GENERATORS { path: 'generator/password', component: GeneratorPassword, }, + { + path: 'generator/qrcode', + component: GeneratorQrcode, + }, { path: '**', redirectTo: '', - } + }, ]; diff --git a/src/app/components/custom-card/custom-card.html b/src/app/components/custom-card/custom-card.html index 330f8bd..6a85138 100644 --- a/src/app/components/custom-card/custom-card.html +++ b/src/app/components/custom-card/custom-card.html @@ -1,8 +1,8 @@ @if (enabled()) {
+ class="h-full hover:cursor-pointer flex flex-col p-6 rounded-lg border border-gray-700 bg-zinc-800 transition-colors duration-200 hover:border-blue-500" + [routerLink]="destination()" + > - {{ description() }} + {{ description() }}
} diff --git a/src/app/components/custom-card/custom-card.ts b/src/app/components/custom-card/custom-card.ts index 51a6c57..cc0051c 100644 --- a/src/app/components/custom-card/custom-card.ts +++ b/src/app/components/custom-card/custom-card.ts @@ -1,7 +1,7 @@ import { Component, input } from '@angular/core'; import { CustomTitle } from '../custom-title/custom-title'; -import {RouterLink} from '@angular/router'; -import {NgStyle} from '@angular/common'; +import { RouterLink } from '@angular/router'; +import { NgStyle } from '@angular/common'; @Component({ selector: 'app-custom-card', @@ -10,7 +10,6 @@ import {NgStyle} from '@angular/common'; styleUrl: './custom-card.css', }) export class CustomCard { - title = input.required(); titleSizeInPx = input(20); titleColor = input(); diff --git a/src/app/components/custom-description/custom-description.html b/src/app/components/custom-description/custom-description.html index fc5dbf4..f7e2d57 100644 --- a/src/app/components/custom-description/custom-description.html +++ b/src/app/components/custom-description/custom-description.html @@ -1,10 +1,10 @@
-

{{descriptionText()}}

+

{{ descriptionText() }}

@if (additionalListEnabled()) {
    @for (item of additionalListText(); track $index) { -
  • {{item}}
  • +
  • {{ item }}
  • }
} diff --git a/src/app/components/custom-description/custom-description.spec.ts b/src/app/components/custom-description/custom-description.spec.ts index 5d5fc62..4f06ec4 100644 --- a/src/app/components/custom-description/custom-description.spec.ts +++ b/src/app/components/custom-description/custom-description.spec.ts @@ -8,9 +8,8 @@ describe('CustomDescription', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [CustomDescription] - }) - .compileComponents(); + imports: [CustomDescription], + }).compileComponents(); fixture = TestBed.createComponent(CustomDescription); component = fixture.componentInstance; diff --git a/src/app/components/custom-description/custom-description.ts b/src/app/components/custom-description/custom-description.ts index 786d152..3afcef7 100644 --- a/src/app/components/custom-description/custom-description.ts +++ b/src/app/components/custom-description/custom-description.ts @@ -1,4 +1,4 @@ -import {Component, input} from '@angular/core'; +import { Component, input } from '@angular/core'; @Component({ selector: 'app-custom-description', @@ -9,5 +9,5 @@ import {Component, input} from '@angular/core'; export class CustomDescription { descriptionText = input.required(); additionalListEnabled = input(false); - additionalListText =input(); + additionalListText = input(); } diff --git a/src/app/components/custom-title/custom-title.html b/src/app/components/custom-title/custom-title.html index a258993..5ec4ae0 100644 --- a/src/app/components/custom-title/custom-title.html +++ b/src/app/components/custom-title/custom-title.html @@ -1,6 +1,8 @@ {{ text() }} + 'font-size': textSizeInPx() + 'px', + color: textColor(), + 'font-weight': fontWeight(), + }" + >{{ text() }} diff --git a/src/app/components/custom-title/custom-title.ts b/src/app/components/custom-title/custom-title.ts index 51b111d..cd977c0 100644 --- a/src/app/components/custom-title/custom-title.ts +++ b/src/app/components/custom-title/custom-title.ts @@ -1,5 +1,5 @@ import { Component, input } from '@angular/core'; -import {NgClass, NgStyle} from '@angular/common'; +import { NgClass, NgStyle } from '@angular/common'; @Component({ selector: 'app-custom-title', @@ -11,5 +11,5 @@ export class CustomTitle { text = input.required(); textSizeInPx = input(16); textColor = input(); - fontWeight = input("normal"); + fontWeight = input('normal'); } diff --git a/src/app/sites/generator/password/generator-password.component.html b/src/app/sites/generator/password/generator-password.component.html index 423ea5a..faf1e97 100644 --- a/src/app/sites/generator/password/generator-password.component.html +++ b/src/app/sites/generator/password/generator-password.component.html @@ -1,62 +1,105 @@
- +
+ [additionalListEnabled]="true" + [additionalListText]="[ + 'Use at least 16 characters for sensitive accounts', + 'Include a mix of letters, numbers, and special characters', + 'Use different passwords for each account', + ]" + >
- - + + +
-
-

+

+ +

@if (getStrengthDescription(passwordGenerator.value.length)) { - {{getStrengthDescription(passwordGenerator.value.length).text}}* + {{ getStrengthDescription(passwordGenerator.value.length).text }}* }

- +
- +
- +

*Based on the length of the password

- +
@if (generated) { -
- -
-
{{generatedPassword}} +
+ +
+
+ {{ generatedPassword }} +
+
-
-
}
-
\ No newline at end of file +
diff --git a/src/app/sites/generator/password/generator-password.component.spec.ts b/src/app/sites/generator/password/generator-password.component.spec.ts index f52e344..8be267c 100644 --- a/src/app/sites/generator/password/generator-password.component.spec.ts +++ b/src/app/sites/generator/password/generator-password.component.spec.ts @@ -8,9 +8,8 @@ describe('Password', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [GeneratorPassword] - }) - .compileComponents(); + imports: [GeneratorPassword], + }).compileComponents(); fixture = TestBed.createComponent(GeneratorPassword); component = fixture.componentInstance; diff --git a/src/app/sites/generator/password/generator-password.component.ts b/src/app/sites/generator/password/generator-password.component.ts index c7c7bbf..6895945 100644 --- a/src/app/sites/generator/password/generator-password.component.ts +++ b/src/app/sites/generator/password/generator-password.component.ts @@ -1,34 +1,26 @@ import { Component } from '@angular/core'; -import {CustomTitle} from '../../../components/custom-title/custom-title'; -import {FormBuilder, FormsModule, ReactiveFormsModule} from '@angular/forms'; -import {CustomDescription} from '../../../components/custom-description/custom-description'; +import { CustomTitle } from '../../../components/custom-title/custom-title'; +import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { CustomDescription } from '../../../components/custom-description/custom-description'; @Component({ selector: 'app-password', - imports: [ - CustomTitle, - CustomDescription, - ReactiveFormsModule, - ], + imports: [CustomTitle, CustomDescription, ReactiveFormsModule], templateUrl: './generator-password.component.html', styleUrl: './generator-password.component.css', }) export class GeneratorPassword { - passwordGenerator!: any; generatedPassword: string = ''; generated: boolean = false; - - - constructor(private fb:FormBuilder) { - + constructor(private fb: FormBuilder) { this.passwordGenerator = this.fb.group({ length: [16], includeLetters: [true], includeNumbers: [true], - includeSymbols: [true] - }) + includeSymbols: [true], + }); } generatePassword() { @@ -38,10 +30,10 @@ export class GeneratorPassword { let includeNumbers = this.passwordGenerator.value.includeNumbers; let includeSymbols = this.passwordGenerator.value.includeSymbols; - if(!includeLetters && !includeNumbers && !includeSymbols) { + if (!includeLetters && !includeNumbers && !includeSymbols) { this.passwordGenerator.value.includeLetters = true; includeLetters = true; - console.log(this.passwordGenerator.value) + console.log(this.passwordGenerator.value); } const uppercaseChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; @@ -55,7 +47,7 @@ export class GeneratorPassword { if (includeSymbols) allChars += symbolChars; for (let i = 0; i < length; i++) { - this.generatedPassword += allChars[Math.floor(Math.random() * allChars.length)] + this.generatedPassword += allChars[Math.floor(Math.random() * allChars.length)]; } this.generated = true; @@ -66,9 +58,9 @@ export class GeneratorPassword { } public getStrengthDescription = (len: number) => { - if (len < 10) return { text: 'Very Weak', color: 'text-red-500' } - if (len < 15) return { text: 'Weak', color: 'text-orange-500' } - if (len < 20) return { text: 'Strong', color: 'text-green-500' } - return { text: 'Very Strong', color: 'text-emerald-500' } - } + if (len < 10) return { text: 'Very Weak', color: 'text-red-500' }; + if (len < 15) return { text: 'Weak', color: 'text-orange-500' }; + if (len < 20) return { text: 'Strong', color: 'text-green-500' }; + return { text: 'Very Strong', color: 'text-emerald-500' }; + }; } diff --git a/src/app/sites/generator/qrcode/generator-qrcode.css b/src/app/sites/generator/qrcode/generator-qrcode.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/sites/generator/qrcode/generator-qrcode.html b/src/app/sites/generator/qrcode/generator-qrcode.html new file mode 100644 index 0000000..7a409bf --- /dev/null +++ b/src/app/sites/generator/qrcode/generator-qrcode.html @@ -0,0 +1,64 @@ +
+
+
+ +
+ +
+ +
+ +
+ +
+
+ + +
+ +
+ + +
+ +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + @if (qrDataUrl) { + Generated QR Code + + } +
+
+
+
\ No newline at end of file diff --git a/src/app/sites/generator/qrcode/generator-qrcode.spec.ts b/src/app/sites/generator/qrcode/generator-qrcode.spec.ts new file mode 100644 index 0000000..d94c402 --- /dev/null +++ b/src/app/sites/generator/qrcode/generator-qrcode.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GeneratorQrcode } from './generator-qrcode'; + +describe('GeneratorQrcode', () => { + let component: GeneratorQrcode; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [GeneratorQrcode], + }).compileComponents(); + + fixture = TestBed.createComponent(GeneratorQrcode); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/sites/generator/qrcode/generator-qrcode.ts b/src/app/sites/generator/qrcode/generator-qrcode.ts new file mode 100644 index 0000000..bd976d2 --- /dev/null +++ b/src/app/sites/generator/qrcode/generator-qrcode.ts @@ -0,0 +1,61 @@ +import { Component, ViewChild, ElementRef } from '@angular/core'; +import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; +import QRCode from 'qrcode'; +import { CustomTitle } from "../../../components/custom-title/custom-title"; +import { CustomDescription } from "../../../components/custom-description/custom-description"; + +@Component({ + selector: 'app-generator-qrcode', + templateUrl: './generator-qrcode.html', + styleUrls: ['./generator-qrcode.css'], + imports: [ReactiveFormsModule, CustomTitle, CustomDescription], +}) +export class GeneratorQrcode { + qrDataUrl: string | null = null; + qrCodeDetailsForm: any; + + @ViewChild('canvas', { static: false }) canvasRef!: ElementRef; + + @ViewChild('ziel') zielRef!: ElementRef; + + constructor(private fb: FormBuilder) { + this.qrCodeDetailsForm = this.fb.group({ + text: ['', Validators.required], + size: [300, Validators.required], + darkColor: ['#000000', Validators.required], + lightColor: ['#FFFFFF', Validators.required], + }); + } + + async generateQR(): Promise { + if (!this.qrCodeDetailsForm.valid) return; + const canvas = this.canvasRef?.nativeElement; + if (!canvas) return; + + try { + await QRCode.toCanvas(canvas, this.qrCodeDetailsForm.value.text, { + width: this.qrCodeDetailsForm.value.size, + margin: 2, + color: { + dark: this.qrCodeDetailsForm.value.darkColor, + light: this.qrCodeDetailsForm.value.lightColor, + }, + }); + this.qrDataUrl = canvas.toDataURL('image/png'); + this.zielRef.nativeElement.scrollIntoView({ behavior: 'smooth' }); + + } catch (err) { + console.error('Error generating QR code:', err); + } + } + + downloadQR(): void { + if (!this.qrDataUrl) return; + const link = document.createElement('a'); + link.download = 'qrcode.png'; + link.href = this.qrDataUrl; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } +} diff --git a/src/app/sites/startpage/startpage.html b/src/app/sites/startpage/startpage.html index 2cbef19..0ada5f7 100644 --- a/src/app/sites/startpage/startpage.html +++ b/src/app/sites/startpage/startpage.html @@ -21,7 +21,13 @@
@for (tool of feature.tools; track $index) { - + }
diff --git a/src/app/sites/startpage/startpage.ts b/src/app/sites/startpage/startpage.ts index 0b7244a..d0eaf2d 100644 --- a/src/app/sites/startpage/startpage.ts +++ b/src/app/sites/startpage/startpage.ts @@ -2,7 +2,7 @@ import { Component } from '@angular/core'; import { NgOptimizedImage } from '@angular/common'; import { CustomTitle } from '../../components/custom-title/custom-title'; import { CustomCard } from '../../components/custom-card/custom-card'; -import {ReactiveFormsModule} from '@angular/forms'; +import { ReactiveFormsModule } from '@angular/forms'; @Component({ selector: 'app-startpage', @@ -11,33 +11,42 @@ import {ReactiveFormsModule} from '@angular/forms'; imports: [CustomTitle, CustomCard, ReactiveFormsModule], }) export class Startpage { - - features = [{ - name: 'Generators', - enabled: true, - tools: [{ - name: 'Password Generator', - description: 'Create secure passwords with custom options', - link: '/generator/password', + features = [ + { + name: 'Generators', enabled: true, - }, { - name: 'QR Code Generator', - description: 'Generate and download QR codes for any text or URL', - link: '/generator/qr', + tools: [ + { + name: 'Password Generator', + description: 'Create secure passwords with custom options', + link: '/generator/password', + enabled: true, + }, + { + name: 'QR Code Generator', + description: 'Generate and download QR codes for any text or URL', + link: '/generator/qrcode', + enabled: true, + }, + ], + }, + { + name: 'Tests', enabled: true, - }]}, { - name: 'Tests', - enabled: true, - tools: [{ - name: 'Test 1', - description: 'This is a just test description.', - link: '/test', - enabled: true, - },{ - name: 'Test 2', - description: 'This is a just test description.', - link: '/test', - enabled: false, - }] - }]; + tools: [ + { + name: 'Test 1', + description: 'This is a just test description.', + link: '/test', + enabled: true, + }, + { + name: 'Test 2', + description: 'This is a just test description.', + link: '/test', + enabled: false, + }, + ], + }, + ]; } diff --git a/src/app/sites/test-it/test-it.html b/src/app/sites/test-it/test-it.html index c3d7063..824c597 100644 --- a/src/app/sites/test-it/test-it.html +++ b/src/app/sites/test-it/test-it.html @@ -4,6 +4,8 @@ + > + Home +
diff --git a/src/app/sites/test-it/test-it.spec.ts b/src/app/sites/test-it/test-it.spec.ts index 868a676..d69dc50 100644 --- a/src/app/sites/test-it/test-it.spec.ts +++ b/src/app/sites/test-it/test-it.spec.ts @@ -8,9 +8,8 @@ describe('TestIt', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [TestIt] - }) - .compileComponents(); + imports: [TestIt], + }).compileComponents(); fixture = TestBed.createComponent(TestIt); component = fixture.componentInstance; diff --git a/src/app/sites/test-it/test-it.ts b/src/app/sites/test-it/test-it.ts index ce67f0f..eb9fb02 100644 --- a/src/app/sites/test-it/test-it.ts +++ b/src/app/sites/test-it/test-it.ts @@ -1,14 +1,10 @@ import { Component } from '@angular/core'; -import {RouterLink} from '@angular/router'; +import { RouterLink } from '@angular/router'; @Component({ selector: 'app-test-it', - imports: [ - RouterLink - ], + imports: [RouterLink], templateUrl: './test-it.html', styleUrl: './test-it.css', }) -export class TestIt { - -} +export class TestIt {} diff --git a/src/index.html b/src/index.html index ef99c4d..67c26b7 100644 --- a/src/index.html +++ b/src/index.html @@ -2,7 +2,7 @@ - ToolsWebsite + Tools Website