From f294ec2e0196dff7f62f4e3550310b8e829fc9d9 Mon Sep 17 00:00:00 2001 From: Sebastian Fastner Date: Mon, 29 Jul 2024 14:55:33 +0200 Subject: [PATCH 1/4] feat: Move favicons from public to processed images --- .gitignore | 8 +- app/components/favicon/FavIcon.tsx | 24 ++ app/components/favicon/icon.svg | 1 + app/root.tsx | 32 +- app/routes/[manifest.webmanifest].tsx | 22 ++ package.json | 6 +- pnpm-lock.yaml | 359 ++++++++++++++++--- public/favicon.ico | Bin 15086 -> 4239 bytes public/favicons/README.md | 1 - public/favicons/android-chrome-192x192.png | Bin 2249 -> 0 bytes public/favicons/android-chrome-512x512.png | Bin 9539 -> 0 bytes public/favicons/apple-touch-icon.png | Bin 2027 -> 0 bytes public/favicons/browserconfig.xml | 9 - public/favicons/favicon-16x16.png | Bin 705 -> 0 bytes public/favicons/favicon-32x32.png | Bin 859 -> 0 bytes public/favicons/favicon.ico | Bin 15086 -> 0 bytes public/favicons/mstile-144x144.png | Bin 1663 -> 0 bytes public/favicons/mstile-150x150.png | Bin 1751 -> 0 bytes public/favicons/mstile-310x150.png | Bin 1996 -> 0 bytes public/favicons/mstile-310x310.png | Bin 3512 -> 0 bytes public/favicons/mstile-70x70.png | Bin 1379 -> 0 bytes public/favicons/safari-pinned-tab.svg | 27 -- public/favicons/site.webmanifest | 19 - tools/favicon-generator/favicon-generator.ts | 50 +++ tools/favicon-generator/ico-endec.d.ts | 18 + tools/favicon-generator/tsconfig.json | 3 + 26 files changed, 439 insertions(+), 140 deletions(-) create mode 100644 app/components/favicon/FavIcon.tsx create mode 100644 app/components/favicon/icon.svg create mode 100644 app/routes/[manifest.webmanifest].tsx delete mode 100644 public/favicons/README.md delete mode 100644 public/favicons/android-chrome-192x192.png delete mode 100644 public/favicons/android-chrome-512x512.png delete mode 100644 public/favicons/apple-touch-icon.png delete mode 100644 public/favicons/browserconfig.xml delete mode 100644 public/favicons/favicon-16x16.png delete mode 100644 public/favicons/favicon-32x32.png delete mode 100644 public/favicons/favicon.ico delete mode 100644 public/favicons/mstile-144x144.png delete mode 100644 public/favicons/mstile-150x150.png delete mode 100644 public/favicons/mstile-310x150.png delete mode 100644 public/favicons/mstile-310x310.png delete mode 100644 public/favicons/mstile-70x70.png delete mode 100644 public/favicons/safari-pinned-tab.svg delete mode 100644 public/favicons/site.webmanifest create mode 100644 tools/favicon-generator/favicon-generator.ts create mode 100644 tools/favicon-generator/ico-endec.d.ts create mode 100644 tools/favicon-generator/tsconfig.json diff --git a/.gitignore b/.gitignore index 073bd8c..a8e3d3d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,10 @@ node_modules .vercel .DS_Store .sst -.tmp \ No newline at end of file +.tmp + +app/components/favicon/apple-touch-icon.png +app/components/favicon/icon-192.png +app/components/favicon/icon-512.png +app/components/favicon/favicon.ico +public/favicon.ico diff --git a/app/components/favicon/FavIcon.tsx b/app/components/favicon/FavIcon.tsx new file mode 100644 index 0000000..806ca1d --- /dev/null +++ b/app/components/favicon/FavIcon.tsx @@ -0,0 +1,24 @@ +// Based upon https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs + +import appleTouchIcon from "./apple-touch-icon.png" +import favIcon from "./favicon.ico" +import icon from "./icon.svg" +import icon192 from "./icon-192.png" +import icon512 from "./icon-512.png" + +export function FavIcon() { + return (<> + + + + + + ) +} + +export function webmanifestIcons() { + return { + icon192, + icon512 + } +} \ No newline at end of file diff --git a/app/components/favicon/icon.svg b/app/components/favicon/icon.svg new file mode 100644 index 0000000..37cc158 --- /dev/null +++ b/app/components/favicon/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/root.tsx b/app/root.tsx index adb0de2..4800e14 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -10,6 +10,7 @@ import { import type { PropsWithChildren } from "react" import { Body } from "./components/body/Body" +import { FavIcon } from "./components/favicon/FavIcon" import { Footer } from "./components/footer/Footer" import { Header } from "./components/header/Header" import { Main } from "./components/main/Main" @@ -22,36 +23,7 @@ export function Layout({ children }: PropsWithChildren) { - - - - - - - - - +
diff --git a/app/routes/[manifest.webmanifest].tsx b/app/routes/[manifest.webmanifest].tsx new file mode 100644 index 0000000..65336d4 --- /dev/null +++ b/app/routes/[manifest.webmanifest].tsx @@ -0,0 +1,22 @@ +// Create webmanifest file with processed icons +import { webmanifestIcons } from "~/components/favicon/FavIcon"; + +export const loader = () => { + const icons = webmanifestIcons(); + + // handle "GET" request + // set up our text content that will be returned in the response + const webmanifest = JSON.stringify({ + "icons": [ + { "src": icons.icon192, "type": "image/png", "sizes": "192x192" }, + { "src": icons.icon512, "type": "image/png", "sizes": "512x512" } + ] + }) + // return the text content, a status 200 success response, and set the content type to text/plain + return new Response(webmanifest, { + status: 200, + headers: { + "Content-Type": "application/json", + } + }); +}; \ No newline at end of file diff --git a/package.json b/package.json index 02d475f..23d60e0 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "test:lint": "eslint .", "test:json-schema": "pnpm create:json-schema ; pnpx ajv-cli -s ./.tmp/data.schema.json -d 'app/data/*.json'", "create:json-schema": "mkdir -p ./.tmp && pnpx typescript-json-schema app/data/data.types.ts ProjectsType -o ./.tmp/data.schema.json --skipLibCheck --ignoreErrors", + "create:favicons": "pnpx tsx tools/favicon-generator/favicon-generator.ts", "fix": "eslint --fix .; prettier --write .", "format": "prettier --write .", "test:check-format": "prettier --check .", @@ -37,14 +38,17 @@ "@effective/eslint-config": "^5.4.7", "@remix-run/dev": "^2.10.3", "@storybook/react": "^8.2.6", + "@tsconfig/node20": "^20.1.4", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@vanilla-extract/css": "^1.15.3", "@vanilla-extract/vite-plugin": "^4.0.13", "@vercel/remix": "^2.10.3", "eslint": "^8.57.0", + "ico-endec": "^0.1.6", "npm-check-updates": "^16.14.20", "prettier": "^3.3.3", + "sharp": "^0.33.4", "sst": "ion", "svgo": "^3.3.2", "typescript": "^5.5.4", @@ -55,4 +59,4 @@ "engines": { "node": ">=18.0.0" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1a99107..82345fd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,6 +48,9 @@ importers: '@storybook/react': specifier: ^8.2.6 version: 8.2.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.6(@babel/preset-env@7.24.8(@babel/core@7.24.9)))(typescript@5.5.4) + '@tsconfig/node20': + specifier: ^20.1.4 + version: 20.1.4 '@types/react': specifier: ^18.3.3 version: 18.3.3 @@ -66,12 +69,18 @@ importers: eslint: specifier: ^8.57.0 version: 8.57.0 + ico-endec: + specifier: ^0.1.6 + version: 0.1.6 npm-check-updates: specifier: ^16.14.20 version: 16.14.20 prettier: specifier: ^3.3.3 version: 3.3.3 + sharp: + specifier: ^0.33.4 + version: 0.33.4 sst: specifier: ion version: 0.1.21 @@ -1012,6 +1021,9 @@ packages: '@effective/shadow@1.0.1': resolution: {integrity: sha512-qmUGNMqLyKuDkVWTWITu3v1ASsLrIExcX+lV0pQ+VpmZX2+ek8ppiOdXx/WRKJwH5T90yJiTESWX2e5jthLzYg==} + '@emnapi/runtime@1.2.0': + resolution: {integrity: sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==} + '@emotion/hash@0.9.1': resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} @@ -1597,6 +1609,119 @@ packages: '@humanwhocodes/object-schema@2.0.3': resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + '@img/sharp-darwin-arm64@0.33.4': + resolution: {integrity: sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.33.4': + resolution: {integrity: sha512-0l7yRObwtTi82Z6ebVI2PnHT8EB2NxBgpK2MiKJZJ7cz32R4lxd001ecMhzzsZig3Yv9oclvqqdV93jo9hy+Dw==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.0.2': + resolution: {integrity: sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==} + engines: {macos: '>=11', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.0.2': + resolution: {integrity: sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==} + engines: {macos: '>=10.13', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.0.2': + resolution: {integrity: sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==} + engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.0.2': + resolution: {integrity: sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==} + engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.0.2': + resolution: {integrity: sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==} + engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.0.2': + resolution: {integrity: sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ==} + engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.0.2': + resolution: {integrity: sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ==} + engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.0.2': + resolution: {integrity: sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw==} + engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.33.4': + resolution: {integrity: sha512-2800clwVg1ZQtxwSoTlHvtm9ObgAax7V6MTAB/hDT945Tfyy3hVkmiHpeLPCKYqYR1Gcmv1uDZ3a4OFwkdBL7Q==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.33.4': + resolution: {integrity: sha512-RUgBD1c0+gCYZGCCe6mMdTiOFS0Zc/XrN0fYd6hISIKcDUbAW5NtSQW9g/powkrXYm6Vzwd6y+fqmExDuCdHNQ==} + engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-s390x@0.33.4': + resolution: {integrity: sha512-h3RAL3siQoyzSoH36tUeS0PDmb5wINKGYzcLB5C6DIiAn2F3udeFAum+gj8IbA/82+8RGCTn7XW8WTFnqag4tQ==} + engines: {glibc: '>=2.31', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.33.4': + resolution: {integrity: sha512-GoR++s0XW9DGVi8SUGQ/U4AeIzLdNjHka6jidVwapQ/JebGVQIpi52OdyxCNVRE++n1FCLzjDovJNozif7w/Aw==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.33.4': + resolution: {integrity: sha512-nhr1yC3BlVrKDTl6cO12gTpXMl4ITBUZieehFvMntlCXFzH2bvKG76tBL2Y/OqhupZt81pR7R+Q5YhJxW0rGgQ==} + engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.33.4': + resolution: {integrity: sha512-uCPTku0zwqDmZEOi4ILyGdmW76tH7dm8kKlOIV1XC5cLyJ71ENAAqarOHQh0RLfpIpbV5KOpXzdU6XkJtS0daw==} + engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.33.4': + resolution: {integrity: sha512-Bmmauh4sXUsUqkleQahpdNXKvo+wa1V9KhT2pDA4VJGKwnKMJXiSTGphn0gnJrlooda0QxCtXc6RX1XAU6hMnQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [wasm32] + + '@img/sharp-win32-ia32@0.33.4': + resolution: {integrity: sha512-99SJ91XzUhYHbx7uhK3+9Lf7+LjwMGQZMDlO/E/YVJ7Nc3lyDFZPGhjwiYdctoH2BOzW9+TnfqcaMKt0jHLdqw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.33.4': + resolution: {integrity: sha512-3QLocdTRVIrFNye5YocZl+KKpYKP+fksi1QhmOArgx7GyhIbQp/WrJRu176jm8IxromS7RIkzMiMINVdBtC8Aw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [win32] + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -2127,6 +2252,9 @@ packages: '@tsconfig/node16@1.0.4': resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@tsconfig/node20@20.1.4': + resolution: {integrity: sha512-sqgsT69YFeLWf5NtJ4Xq/xAF8p4ZQHlmGW74Nu2tD4+g5fAsposc4ZfaaPixVu4y01BEiDCWLRDCvDM5JOsRxg==} + '@tufjs/canonical-json@1.0.0': resolution: {integrity: sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -2752,10 +2880,17 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + color-support@1.1.3: resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} hasBin: true + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} @@ -2981,6 +3116,10 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} @@ -3669,6 +3808,9 @@ packages: humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + ico-endec@0.1.6: + resolution: {integrity: sha512-ZdLU38ZoED3g1j3iEyzcQj+wAkY2xfWNkymszfJPoxucIUhK7NayQ+/C4Kv0nDFMIsbtbEHldv3V8PU494/ueQ==} + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -3762,6 +3904,9 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-async-function@2.0.0: resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} engines: {node: '>= 0.4'} @@ -5267,6 +5412,10 @@ packages: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} engines: {node: '>=8'} + sharp@0.33.4: + resolution: {integrity: sha512-7i/dt5kGl7qR4gwPRD2biwD2/SvBn3O04J77XKFgL2OnZtQw+AG9wnuS/csmu80nPRHLYE9E41fyEiG8nhH6/Q==} + engines: {libvips: '>=8.15.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -5291,6 +5440,9 @@ packages: engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} hasBin: true + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -6442,12 +6594,12 @@ snapshots: '@babel/helper-annotate-as-pure@7.24.7': dependencies: - '@babel/types': 7.24.7 + '@babel/types': 7.24.9 '@babel/helper-builder-binary-assignment-operator-visitor@7.24.7': dependencies: - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 + '@babel/traverse': 7.24.8 + '@babel/types': 7.24.9 transitivePeerDependencies: - supports-color @@ -6508,21 +6660,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-create-class-features-plugin@7.24.8(@babel/core@7.24.9)': - dependencies: - '@babel/core': 7.24.9 - '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-member-expression-to-functions': 7.24.8 - '@babel/helper-optimise-call-expression': 7.24.7 - '@babel/helper-replace-supers': 7.24.7(@babel/core@7.24.9) - '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - '@babel/helper-create-regexp-features-plugin@7.24.7(@babel/core@7.24.0)': dependencies: '@babel/core': 7.24.0 @@ -6633,7 +6770,7 @@ snapshots: '@babel/helper-optimise-call-expression@7.24.7': dependencies: - '@babel/types': 7.24.7 + '@babel/types': 7.24.9 '@babel/helper-plugin-utils@7.24.0': {} @@ -6671,15 +6808,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-replace-supers@7.24.7(@babel/core@7.24.9)': - dependencies: - '@babel/core': 7.24.9 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-member-expression-to-functions': 7.24.8 - '@babel/helper-optimise-call-expression': 7.24.7 - transitivePeerDependencies: - - supports-color - '@babel/helper-simple-access@7.22.5': dependencies: '@babel/types': 7.24.0 @@ -6697,8 +6825,8 @@ snapshots: '@babel/helper-skip-transparent-expression-wrappers@7.24.7': dependencies: - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 + '@babel/traverse': 7.24.8 + '@babel/types': 7.24.9 transitivePeerDependencies: - supports-color @@ -6728,8 +6856,8 @@ snapshots: dependencies: '@babel/helper-function-name': 7.24.7 '@babel/template': 7.24.7 - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 + '@babel/traverse': 7.24.8 + '@babel/types': 7.24.9 transitivePeerDependencies: - supports-color @@ -6876,11 +7004,6 @@ snapshots: '@babel/core': 7.24.0 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.9)': - dependencies: - '@babel/core': 7.24.9 - '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.0)': dependencies: '@babel/core': 7.24.0 @@ -6901,11 +7024,6 @@ snapshots: '@babel/core': 7.24.0 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.9)': - dependencies: - '@babel/core': 7.24.9 - '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.24.0)': dependencies: '@babel/core': 7.24.0 @@ -6977,7 +7095,7 @@ snapshots: '@babel/plugin-transform-class-properties@7.24.7(@babel/core@7.24.9)': dependencies: '@babel/core': 7.24.9 - '@babel/helper-create-class-features-plugin': 7.24.8(@babel/core@7.24.9) + '@babel/helper-create-class-features-plugin': 7.24.8(@babel/core@7.24.0) '@babel/helper-plugin-utils': 7.24.8 transitivePeerDependencies: - supports-color @@ -7121,6 +7239,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-modules-commonjs@7.24.8(@babel/core@7.24.9)': + dependencies: + '@babel/core': 7.24.9 + '@babel/helper-module-transforms': 7.24.9(@babel/core@7.24.0) + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-simple-access': 7.24.7 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-modules-systemjs@7.24.7(@babel/core@7.24.0)': dependencies: '@babel/core': 7.24.0 @@ -7160,7 +7287,7 @@ snapshots: dependencies: '@babel/core': 7.24.9 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.9) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.0) '@babel/plugin-transform-numeric-separator@7.24.7(@babel/core@7.24.0)': dependencies: @@ -7204,7 +7331,7 @@ snapshots: '@babel/core': 7.24.9 '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.9) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.0) transitivePeerDependencies: - supports-color @@ -7224,7 +7351,7 @@ snapshots: '@babel/plugin-transform-private-methods@7.24.7(@babel/core@7.24.9)': dependencies: '@babel/core': 7.24.9 - '@babel/helper-create-class-features-plugin': 7.24.8(@babel/core@7.24.9) + '@babel/helper-create-class-features-plugin': 7.24.8(@babel/core@7.24.0) '@babel/helper-plugin-utils': 7.24.8 transitivePeerDependencies: - supports-color @@ -7420,7 +7547,7 @@ snapshots: dependencies: '@babel/core': 7.24.0 '@babel/helper-plugin-utils': 7.24.8 - '@babel/types': 7.24.7 + '@babel/types': 7.24.9 esutils: 2.0.3 '@babel/preset-typescript@7.23.3(@babel/core@7.24.0)': @@ -7569,6 +7696,11 @@ snapshots: dependencies: bezier-easing: 2.1.0 + '@emnapi/runtime@1.2.0': + dependencies: + tslib: 2.6.2 + optional: true + '@emotion/hash@0.9.1': {} '@es-joy/jsdoccomment@0.42.0': @@ -7887,6 +8019,81 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} + '@img/sharp-darwin-arm64@0.33.4': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.2 + optional: true + + '@img/sharp-darwin-x64@0.33.4': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.2 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.0.2': + optional: true + + '@img/sharp-libvips-darwin-x64@1.0.2': + optional: true + + '@img/sharp-libvips-linux-arm64@1.0.2': + optional: true + + '@img/sharp-libvips-linux-arm@1.0.2': + optional: true + + '@img/sharp-libvips-linux-s390x@1.0.2': + optional: true + + '@img/sharp-libvips-linux-x64@1.0.2': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.0.2': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.0.2': + optional: true + + '@img/sharp-linux-arm64@0.33.4': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.2 + optional: true + + '@img/sharp-linux-arm@0.33.4': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.2 + optional: true + + '@img/sharp-linux-s390x@0.33.4': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.2 + optional: true + + '@img/sharp-linux-x64@0.33.4': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.2 + optional: true + + '@img/sharp-linuxmusl-arm64@0.33.4': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 + optional: true + + '@img/sharp-linuxmusl-x64@0.33.4': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.2 + optional: true + + '@img/sharp-wasm32@0.33.4': + dependencies: + '@emnapi/runtime': 1.2.0 + optional: true + + '@img/sharp-win32-ia32@0.33.4': + optional: true + + '@img/sharp-win32-x64@0.33.4': + optional: true + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -8558,7 +8765,7 @@ snapshots: dependencies: '@babel/core': 7.24.9 '@babel/preset-env': 7.24.8(@babel/core@7.24.0) - '@babel/types': 7.24.7 + '@babel/types': 7.24.9 '@storybook/core': 8.2.6 '@storybook/csf': 0.1.11 '@types/cross-spawn': 6.0.6 @@ -8676,6 +8883,8 @@ snapshots: '@tsconfig/node16@1.0.4': optional: true + '@tsconfig/node20@20.1.4': {} + '@tufjs/canonical-json@1.0.0': {} '@tufjs/models@1.0.4': @@ -9477,8 +9686,18 @@ snapshots: color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + color-support@1.1.3: {} + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + comma-separated-tokens@2.0.3: {} commander@10.0.1: {} @@ -9548,7 +9767,7 @@ snapshots: core-js-compat@3.37.1: dependencies: - browserslist: 4.23.0 + browserslist: 4.23.2 core-util-is@1.0.3: {} @@ -9673,6 +9892,8 @@ snapshots: detect-indent@6.1.0: {} + detect-libc@2.0.3: {} + diff@4.0.2: optional: true @@ -10692,6 +10913,8 @@ snapshots: dependencies: ms: 2.1.3 + ico-endec@0.1.6: {} + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -10773,6 +10996,8 @@ snapshots: is-arrayish@0.2.1: {} + is-arrayish@0.3.2: {} + is-async-function@2.0.0: dependencies: has-tostringtag: 1.0.2 @@ -10966,9 +11191,9 @@ snapshots: jscodeshift@0.15.2(@babel/preset-env@7.24.8(@babel/core@7.24.9)): dependencies: '@babel/core': 7.24.9 - '@babel/parser': 7.24.7 + '@babel/parser': 7.24.8 '@babel/plugin-transform-class-properties': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.24.9) + '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.24.9) '@babel/plugin-transform-nullish-coalescing-operator': 7.24.7(@babel/core@7.24.9) '@babel/plugin-transform-optional-chaining': 7.24.8(@babel/core@7.24.9) '@babel/plugin-transform-private-methods': 7.24.7(@babel/core@7.24.9) @@ -12586,6 +12811,32 @@ snapshots: dependencies: kind-of: 6.0.3 + sharp@0.33.4: + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + semver: 7.6.0 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.4 + '@img/sharp-darwin-x64': 0.33.4 + '@img/sharp-libvips-darwin-arm64': 1.0.2 + '@img/sharp-libvips-darwin-x64': 1.0.2 + '@img/sharp-libvips-linux-arm': 1.0.2 + '@img/sharp-libvips-linux-arm64': 1.0.2 + '@img/sharp-libvips-linux-s390x': 1.0.2 + '@img/sharp-libvips-linux-x64': 1.0.2 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 + '@img/sharp-libvips-linuxmusl-x64': 1.0.2 + '@img/sharp-linux-arm': 0.33.4 + '@img/sharp-linux-arm64': 0.33.4 + '@img/sharp-linux-s390x': 0.33.4 + '@img/sharp-linux-x64': 0.33.4 + '@img/sharp-linuxmusl-arm64': 0.33.4 + '@img/sharp-linuxmusl-x64': 0.33.4 + '@img/sharp-wasm32': 0.33.4 + '@img/sharp-win32-ia32': 0.33.4 + '@img/sharp-win32-x64': 0.33.4 + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -12613,6 +12864,10 @@ snapshots: transitivePeerDependencies: - supports-color + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + sisteransi@1.0.5: {} slash@3.0.0: {} @@ -12715,7 +12970,7 @@ snapshots: storybook@8.2.6(@babel/preset-env@7.24.8(@babel/core@7.24.9)): dependencies: '@babel/core': 7.24.9 - '@babel/types': 7.24.7 + '@babel/types': 7.24.9 '@storybook/codemod': 8.2.6 '@storybook/core': 8.2.6 '@types/semver': 7.5.8 diff --git a/public/favicon.ico b/public/favicon.ico index 1b8fa9b405eb010ab11fd207fa4aaf97d311e6bf..fe414615223a73f2a66df6502fc175ef53403bce 100644 GIT binary patch literal 4239 zcmZQzU<5)11qL9=!B8o{z#zuJz|a}s=g!L|#RX*YdV0770coHL1_cf_AX!{h^#w?A z7I;J!Gca%qgD@k*tT_@43O6EM_@v5 z`p3hU{~uP({r~;;Q@9uw2JSR)|IU4IK8GbX5RGj4wC<_!#OPw^^#A?4_i*z;mY-FO z`G1tb<^L(MkpEvV--pYgF>pJezNijv0Y1w?a#5ZU|9|}W0XF;lz32bW$VY=M2RQ(Q zpLDE1vlq_A?SPYqPyBZ=Z~{95m(M|#M|wp3fBF0+*hFNX!z_PLHXCjm76xtyfE3@n zdh`Feljq?2kb|8HmV?a2?*O>XK*p>IGf|=>%r*4?^C!>2O33gz%xK~qKqJdRjv(v+ zN-RHh^b{}}Z@_$ujmGZ)N-SSGdkHwoKnWR?pm6})4p=yS0ZN=Br}jTzzW+a?fST1F z*35_70ka&GP(ir4tPw7U#=z}>NB1B84|WU$8-SePKnDDJ@$Ua|c29U-$7gwvL%{z> z_aC9z3+Li?07%K>2ao^HpE~dV>zA+LI$(^qn~sAEoX5?G>UhQcrPPqdpw45>rtX;AOCBZ>b`$LeSqyX~MKygYT+yP`- z4ss~@4uCb)D6pI|2Y_^gx@DjOivmD?2vA@tvR1GI{s2V=3jYwZjgTe~DWM4fzu0a6 literal 15086 zcmeI3TTB#J7{{k+lQw^TQPxJ$TOh>8-#y+f#aL=ct;g5Yr6PA?LK4)NR~agXbn_Xt9+c*A4j zJ)(>7lDOf#WDn2m)PITS#sc03MfQbkDEozMT=~aF$7pZ`l)5fG92&UrqrriO z^yjzm*1(NFOd7cIhd~2(e$E=g!p~7d*!X1)FUD^T{mS*ODz{$7%n8*ejQV|jWi4m4jF#qJU2Z7d25_7#ec4%TJxEO z2LF0+_D#^b`x|X*_^iB212^E5DgNo{X)4Gq)Yaf$56#~W)7tyAHI!s^F%Ww7aG|<} zxlboyiXXn=)R43HAWcn8=^!(wP4n~C;Bva?#0Mv-`poAvIXTHd8YF_^=dHnjQ}0sH z{1K+X5`P3~u*@GJ8cg%!ojU*NdHT4xoJQTF%JayxT~dPRADH3?JK8k)`@1z^8x6aL zm0aghgDL*6s=ij(BTR!S{)&@l0{EdLn0knNdM%B(MwB|kLDM%bT63@Vce>_yKXb26 z!W2LHZ`%`h*w)bA)*gVN)z`>e{2PrrZw1_|al#Zo{Lp{ixoMZC28=Ucyg@dt_u)|X zVfk{v9`zvimtI-&JB%lI?*R@h zD1JBuqXGAGwxIdJ6G0j*@kfvb%lr|d!4`i6Xt2#c&l*C)4-M`Sx8XO=J?zG9p|+6m z1I$Q6;gOtv%bSGm&E++Z>ZM--8l|_31FR;L)?~&o3c(zT+8Ke;^Q$fj~llJ*yLjm z?Ut?UY8Q2P_E`289WBT2?&zi$maV6R#3i$4D?WnQWUw9ICPPT#+h8z^-`mwIjf-P0(BB$soRs$9 zC8|8!t6Z{B7rOD$uB>0NQF^|TR&ApGYqR5?t^pr2K3cwib{@R4^eppC;=Sn6Z=-bM zpFUB+LtmEIai&1Ut_| zfby9Wy794|2G0)Kb<91>7Geh7_&IwIFwef40b>U0?@r2^RPuVg5@LUcM{1YUYfP$+ zuxou}E#h7`KE7k|OB0wldJNHvW0-k2^}Ct)Kr?mzsrz$GH$E8UK8{*zW!YH;zqFu? zHbf^<-H-LkIr#t#SReH76~py1hVhZtTnutNi~Bj_b7n9VpCg0m_?#GmiVud4e>wu* z3zKVt;O=ih$43VK3~yy*`R8jkZ7IH*0exQl4zg&L%Yl2^Y<`4ShP!A3C4N!9I3ck*NDr5X{zTxLaLcb|#bu#nYPUWLM4Db&!4^4mM@ymC$l9oMN dURB5QKi2h^^T0b~V21t%e)6R$|Mno*^#AglM6v(? diff --git a/public/favicons/README.md b/public/favicons/README.md deleted file mode 100644 index ce373d8..0000000 --- a/public/favicons/README.md +++ /dev/null @@ -1 +0,0 @@ -Generated by https://realfavicongenerator.net/ diff --git a/public/favicons/android-chrome-192x192.png b/public/favicons/android-chrome-192x192.png deleted file mode 100644 index 512923bc838b72ead1780dc1ca4d58e1fe0310e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2249 zcmZ`(XH=7E7JkzP2p}_p13D-f5p_pOL>L8xFJL0QND~VXq>EC+M2g8LYhl&`=%6T7 z4qzEYFbEbPL69y*lnwz=jI;;|2_$^U#vgn3?2o(hm4gh=}0Ewam^8iRB z0x&}bz%mB_?by7RhxP-2TJmu5rpW&j)1Rgn<`;OMzxW;W^>;ZoH!}zAvi2o=Q#}HN z0^zv?CdtrdWMDWiEB9bFB8<(;=n>#*FeLi_KLMD^BS~)xKa~$X!D9tN5PftsU zPHuhOf*^=gDz!5vo$w4AA08Kr#ql9=4(12D+q>k5Owcy)HNR&1`jZ7#%bGwG7aVK9 zhw`@d?cAf+Z}kJ-0CJ0p^F-nuM6@!QoZq`AQu38QnUvqPGiY^sKJG+J|GR!~J5SNF z=w3lt#F21UOXr~vLr!}g?9C`QFK3@PM3qP++=QH|3uPaA-t!muqoLR2GFel7ldTcd z)6r8?QA6Hscb@)F-Zbys+g>kQ&*A=IIG%C9#P-kB^!eHO#czu*Sufk)v_G$`;f{<~ zJz~{7sUG?;7(g*C-l zplP0NUcC`Ynks#!th&D;ovgl_ZDt0m1!dc3)6i6Z5AaA8 z4=389DvWo6ejJYTlJEyfFqn#IzFJ7!-3`Z0i^?%t+ZRLy4(f={%C#@%A3#re7iuC)GVS$ zAG86tk#YlVc#c6oyahZSLiX^xP(^O?N4{h>kubZ`2Z={jzuv;>2rr`zB?hSNNE*mx zSipzaI-G}rcxt~1wqo`cN=I}V7)lL58G;5QvRF8dN#wkQw5a2H$`yPK47o=Sn|>F< z{zzd0!Zikyv<(@D{Um2my}}gq$FE`x`8^+({(!5*nT^S}4v+4rm2O2>NWRomsWYBZ zgUo<0Q(C+fewiOrJEOEEl{aaS0i$YV*RtHL^iEgJly*2FthLIPEWnpFr|ocR6nyg9 zM=V-Bg!#@ij!}APVIt)5YkFBB-M;_W_>DmB&(4sb;CYht zrmT3g6<5(fSncIWG4(!D-8z4EXXBQO$X3w7P=O=afKv_WdhjKIcOf0>m>!n zFQK;bG|){wdg%0G2>fWzh6vXgF(gBz9*&S$qn0IH-}(P;0iI)qi|4Fsp`0lUjHHOw z%csZ0nSd&nVH$T?uGp*tbNr}Rbq|}}FRq|z5)1Se(%*%@Qc*CXSLO3KcK*^5c+2== zQ(T8XkLsDHFJux)d?~cwUqC_4AYEq-RVJ31*TlWS!G$hk2zjel)(K8$Fuj->>D!rk{^ql?TfA!k>5b=(- zHm{>dr}P}&wobOq0%7r&F|5KA``<;K-=O%3QwYvpH5Qpm`Ix}g)g4@8%lac4oKO|q zsqk#>EBVTerA@;EX13G>NV8&I)t-qY%9pb5xMQW2CN9>i;z?$Czsx5ig#9Kemm*aM zPZ0@RzquHh0bd!X;WKPgQhlH{;2p*hB<8401_hJ_YJi!;m?FtDP{A+&<$+3I?l6iV zH3vNm9H`dQxIbXBXvZ`IV;Mhiqzxby`njk_0~aCGNBxG7U^i%8(R&Td@x}t?BrKYB zLUwZ4M-_1VF+*zt`VQw`FDl{pl~f@?@GnP^3IWHpl%X@xe<+_ZT1sAK8NrCQ>izXa zlB`>O*=RpVcrlC&&$f(v-o$Yj-&~PQFq9!X5=sK|m*f>664XXAmfX`AC$75}IKjp9cO38IBs2FHgg2$&L0&5Ve9 zjZF7?@3ycsv#{J_x{FA(Bob3$miGS`PRE2qh9&)fgZh~2-wMOV?-RUY!f5oM_)tKn z(~TpeqY{FHVndB%;=^+n_HR-=I-Kn7NAnD#6Jq0I!Xi(F5@<=Wp@hg-S}*`-@}`#5 zl;eDN?reAO=yd$-2{8Jq#=)wZ`kKx+v@n_kGHliug3)Jr6FLUpw>EV)={6~Kzz#)D Z#$ZPKC)$#odA4E%aHP1A%k8LX{|2ZXT0j5* diff --git a/public/favicons/android-chrome-512x512.png b/public/favicons/android-chrome-512x512.png deleted file mode 100644 index 768823810b910995107b2cc15f3b21ca5c0ef236..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9539 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 L?N7J4{PBMPOo&<| diff --git a/public/favicons/apple-touch-icon.png b/public/favicons/apple-touch-icon.png deleted file mode 100644 index e2c271ed48d248f58f7ac3c0385f535353937ba9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2027 zcmZ`(Z8*~l8~-~KN+oB~8HsZ0c&;M$LUwYpnb$RhV)K@_zj=vaEK+1zZ(Az8U=$@M zjHlX4SI7x@+4k3D%9g0pA&p6>VXS9;cs@KIp8LA)`@Vj^`~F?`hx@+nv;MxG>(-d9 z0RUi~w-+Hmn*~4I0H%#=;NP?n(2d8DZ~$<>$Z$Dol@?pYcmJRIN>|2i*eeZ`a?vdgIj5LbY=CbCYnY?%8aoRI{kAC@#-SKe4>Ly!g+gjKb=I zc{~RQy&L>L6x`MoxTJkw(cHcHr{Z=CGwUQZ1YBBNI-PSWf)rL)RU1YORZJ)f z8O+P9OL#li+RD2FF9y6Y9%Qc&&dKx7+d9)@(+Ku>ccfcpJYD!)c={NthRTf@au$tyY&Hwx?&h~TO@#+d4ITTO_n<4kdU$&(W0Wz9 z%ow#S7Wc(xIes1)*%55YZn<*R+wf;Wx3^?97I*BTZbc;=?L4;8+9*7Nd@7(rGIrIc zN@_!wuMK2M5GWrG&ZrcZXpl3+K42}8foII}8@Dv12ORvc4?D^WIwEAyr{z7d?2i*R z{JJ^w@W+lXYb_^HSUFF+r>H+|TrUE(6Whn@QlGzoaq^upwMaSyFNJa^dMK*h#gCz6 z>UGdg5Qu`y8%p(+L*jz0Bjc{WJE1Dya+Uo*fk}cwnW=5`BZ8@*8ei@o9WVha8w^|; zW0A$Gny*@Zyoy2bx$#(h1H~B0{e{xea(JQjRD-*IxZttv+K%nS>roPL{Ab13&i4I> z8u67R$bC>0eA0r*eQr?bRwou)DW^_$m z!o-D;Ilar|TF$Si10=W92bg*YjUtiosav_5I&*1BRoS7xRP-tLPGp7h<+$>X_Q`L0 z(F5VvlH4*?w6cVWaMMidinoJ2&@89ut$c|4-By4ekf;@{NH{Tq9}I584vrO<<{+KQEZR7q)CaBY7EeRps5*QM zr9Jt)sYB?kIB^zrD}N(Jn9MXqg;tJ<$Ei5J1LbA%Ia7@JtvCpzM)8d)^5g6Y818g|o$qpw9^=W>GhCK^mJc%^UbswRJq>yXU{s9wo8#xV?!M=;8eb zlPWDru44Tb@2s*=cJidFdUrK7$@uVVs%UJp8aCe$aPD@`_%KZQnf1 z$Bh1oCUq)|t1ck*jdnq;$4%Bf^xbsV8p6#;PL`f<7YBBiFe}!J&00M#VEZ=f7R`Va zcDsodsq6K&n7_h4A=lq*Jc``2JP`d5?YYijQW-`ua#8=jG`H!w<+e+Ax=J#g9>qjH z%?W>Sd3_54-F95xfqA22UgIVoUNnyJaQTw>Zs6nY$hpXWkj=RfTez~VWiO`IL)0wR zIJz0nFSDr1hEgPA@Hc7--w@p_(b zAba#nHr@@gLce0;n9v5aobB2H8PJL4i=jm;@2ut-j}iIPEbe0e#(nR=6Z3v8rIss( zsd~ImKH7qYQ~zQQz0UNAM_AabU$qRnIAR?PrFPM?Wr_I+sh?53F(~c3)3%<o*Xi@gNPQ_Zl$c{WAb zN41^q9zu_eqQ_xl(&MxVK-weGw)Rf8NT(nNXDr$oi^S}-x5wJsXL30D|06h(8k+!S z|9^q51kcHc4p3||rqALrSG6MmZ+BlpBmQu~e*gkI;0yo& diff --git a/public/favicons/browserconfig.xml b/public/favicons/browserconfig.xml deleted file mode 100644 index d469e48..0000000 --- a/public/favicons/browserconfig.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - #da532c - - - diff --git a/public/favicons/favicon-16x16.png b/public/favicons/favicon-16x16.png deleted file mode 100644 index 6722d9a98d7c77f35d48bad26164ed20a1070984..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 705 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>wqx-Glf=BZ8c zp819M%Z`b2`JO7X@Oh*rdD+Fui3O>8`9xlq$-qD7Nja< z7L+72FjUNW{E3I7Fib<^l>g~7o=<}qn3cKplDUPIg}o<>FbgZVG?*MtVOHK8qHy}g ol@mwK9FaM~e!9V9ftMb`D{;Y+Pfn&&fmSehy85}Sb4q9e0GU(_O#lD@ diff --git a/public/favicons/favicon-32x32.png b/public/favicons/favicon-32x32.png deleted file mode 100644 index 26b3577f37766dd2cf802de56909914e0b9f84cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 859 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10;#h!Bi0gkCxOeN`gS!s` zZ2bc4{Oq-DOVdj>t=jnT-orq9|D|)5%$Ybl#3|_L{v$sgzI<3U_xtUq_wU?ay=c|6 z?x`+@PVe8nKdTsXl)>ecSjgAQ_v?%5qC6vh{P^+x-t#l^(N8*7oIHHO#lUISgqdNk zq0gT@e^562=GB|$PM$k;^wiC(HNRNn@&tLxe^8JiL^uwC@&1H>`?mrB6 z4E*)t-Enr$AcufQ_a8le@Ob{zd9Po-e!J=T(YN51@~jN`m}? ze}1eC4|N0b7?Zr+T^Kr8Wj%l#&H|6fVj#U0gc&U_oSP41u$OrHy0X7umligZIe)xT z6e#rE)5S5w;`G$Zxxq~i0tX7C4)~tfbmo&+x53t$7oJ;!PXGBAzbZQY%I)2)MfVNP zystmZ$1Eq(|NO1=568j>?MoMEd~iN;xT!(r^iM~TZ2MF99gBX>Hgo9r2FEeoH;u&x5Cm)H{;iz2js2{{PRO`ZEXh1wTlyZgVcp2YOkx z#5JNMC9x#cD!C{XNHG{07@6oAnClvuhZtH~nOIsGS!f#=SQ!|IM7=qVq9HdwB{QuO zw}w>qkZPa?NstY}`DrEPiAAXl<>lpinR(g8$%zH2dih1^v)|cB0TqQ;g+!DDC6+4` z6y>L7=Ai4 diff --git a/public/favicons/favicon.ico b/public/favicons/favicon.ico deleted file mode 100644 index 1b8fa9b405eb010ab11fd207fa4aaf97d311e6bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 zcmeI3TTB#J7{{k+lQw^TQPxJ$TOh>8-#y+f#aL=ct;g5Yr6PA?LK4)NR~agXbn_Xt9+c*A4j zJ)(>7lDOf#WDn2m)PITS#sc03MfQbkDEozMT=~aF$7pZ`l)5fG92&UrqrriO z^yjzm*1(NFOd7cIhd~2(e$E=g!p~7d*!X1)FUD^T{mS*ODz{$7%n8*ejQV|jWi4m4jF#qJU2Z7d25_7#ec4%TJxEO z2LF0+_D#^b`x|X*_^iB212^E5DgNo{X)4Gq)Yaf$56#~W)7tyAHI!s^F%Ww7aG|<} zxlboyiXXn=)R43HAWcn8=^!(wP4n~C;Bva?#0Mv-`poAvIXTHd8YF_^=dHnjQ}0sH z{1K+X5`P3~u*@GJ8cg%!ojU*NdHT4xoJQTF%JayxT~dPRADH3?JK8k)`@1z^8x6aL zm0aghgDL*6s=ij(BTR!S{)&@l0{EdLn0knNdM%B(MwB|kLDM%bT63@Vce>_yKXb26 z!W2LHZ`%`h*w)bA)*gVN)z`>e{2PrrZw1_|al#Zo{Lp{ixoMZC28=Ucyg@dt_u)|X zVfk{v9`zvimtI-&JB%lI?*R@h zD1JBuqXGAGwxIdJ6G0j*@kfvb%lr|d!4`i6Xt2#c&l*C)4-M`Sx8XO=J?zG9p|+6m z1I$Q6;gOtv%bSGm&E++Z>ZM--8l|_31FR;L)?~&o3c(zT+8Ke;^Q$fj~llJ*yLjm z?Ut?UY8Q2P_E`289WBT2?&zi$maV6R#3i$4D?WnQWUw9ICPPT#+h8z^-`mwIjf-P0(BB$soRs$9 zC8|8!t6Z{B7rOD$uB>0NQF^|TR&ApGYqR5?t^pr2K3cwib{@R4^eppC;=Sn6Z=-bM zpFUB+LtmEIai&1Ut_| zfby9Wy794|2G0)Kb<91>7Geh7_&IwIFwef40b>U0?@r2^RPuVg5@LUcM{1YUYfP$+ zuxou}E#h7`KE7k|OB0wldJNHvW0-k2^}Ct)Kr?mzsrz$GH$E8UK8{*zW!YH;zqFu? zHbf^<-H-LkIr#t#SReH76~py1hVhZtTnutNi~Bj_b7n9VpCg0m_?#GmiVud4e>wu* z3zKVt;O=ih$43VK3~yy*`R8jkZ7IH*0exQl4zg&L%Yl2^Y<`4ShP!A3C4N!9I3ck*NDr5X{zTxLaLcb|#bu#nYPUWLM4Db&!4^4mM@ymC$l9oMN dURB5QKi2h^^T0b~V21t%e)6R$|Mno*^#AglM6v(? diff --git a/public/favicons/mstile-144x144.png b/public/favicons/mstile-144x144.png deleted file mode 100644 index e88b3f3e28a178477ffd2e4be5fa080841a93685..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1663 zcmZ`&c~F!07X5_~LPZ*QAc}>&Z**8%!51S|p?pdpfgnV}ViCeBK|%%DzDky&2?T*4 zBveIcX$U+jR0UCZ;=;a&WzlMbVi8ahR->;#L&E;jKl(@icz5RBGw05nId|sH$)g|h zGTyRt3jn~_n@SGQq2$jtMC;}+CI1lVKtGN|BLQ$*Y_t}Q(Qzn-8bAYpYYPBh2*8SN z#h(G-YXSgsQ2@A<0I)r|?18^404Rj+8${XstJc@obGX@;a=+c!*f_EW&f#6Sda<~x zx$~<~mit~elH-xp)zy>!QFpH2&Pe{|EbHr)<(0nfpR?J*#E8?}1a^JRt!3@<%F2o` zJuBRoF*%`JTTrhrX?bV3LGA&{x5|x`Rb_6?0L174xjQnJT)erl5qT`Uv9?i=cE0F>1UZ!^|3xkl78Yg}ym&VBI!=Pbrha>&=zQuq z0m5&**$_bsn^sN-dmg|2Q~jC9gn>u>V@X%m*4EOPDb>WobpJxMVnhPbRqEthzDenJz0XFD)#YlGHu1i`KlJ z?6(RLoy*gX&pc}HNs2n-NhDK<9;X@cEln+&(W$2n%pN_;1ix~w^5ICN=%xSpH|#RC zd|a#5vO?m%la%_o(o}P*D0)Q8-R3Kz%cJ8_&vlQ{LjsNkjZFes8RTND zsXBs1ylE8d4E7VVeb)Edy|Vy7U-c%Fg4n;kf2|3YyP05<2T*7W2Scj!wjwisRg1u0 zBx?ELy{bjC^mO%5A7*b;!xyVR48oC9y@NhWi+7s#-_Q8oiLBmcY#eVyq#N|PS=uKG zEbN2hWMMIZX|N!*fV{)h!0A0I50Y8pJcVG81MLDe6QtZV(tQgN<@B5^8(;b3r&$&} zR>%X{XE;ZV@2hjNuW+?2A5-)4$h6zfpDHj%?;RoEc#gK=ez|J9%h^7@nMHe8?e%fM zLM|y3|0#8FxBe`L2~os`RkKC>AXraQ*K1v+N->D%g^}j)UXs>cWAk=}{+72XD9rpJ zekWT+61cvQ(eVsAL2UE5v*GT)8%~F(Lni;7opo$dPZ|e@w4pE)aN;L%jMalf_a3!R zb#xY2)S5`Ls;{xwj0&p}6qG-|GtYW<_QY8ecsq(L5&D}7kBhwy#H^2vToK`-d7+5Zt1neV;0=(@ znY_uaqZc1-hezS9EQfnJsQ;92egF1aM(dIKoI$ywdWv`BxL*anwRkYUlkIRlqxIHn zMpEwl9X-luwU=$^lWvANT)EAOCf2W-Gvy=j2Pjs&pE{!05}-Mh`3HPP2Jm)tL$MKc z#`&Ex1!T_;X9@93w;IeZt4f8u1X71_nRWh_w0Z(wa4RS4>Xphunlgz4$Jpo zXtuSRh{G`Rtk0W@k%=#Ym>>MiM@`uu3iC-rl@uxK@u-K!7fx-s$yy?73Zy3v-|R-m z8XeL-!bCq)J~kh*#^>GsS8^r&5^dT zm*>>qhk8v@3~|if<&pGX%QXKq!4F8+1mg0;=a+XTner}=eN)6k-0=8q60sLrIq46U zIln`GI4k8lQdTn@C27MN>9J*y5c^Rkn-5*YV)Zyt&}A$plj8=JVbOYA2&%%OGPyvO zG+u-UGgvvAUHgZfT!CB3R%^4a)#KZfW)8~HU|qm9;mrK&Ir?Y0jSQAmMk^-2X_iEN-*DBp}jT$hrV+$XxPmHbMG_zDCt-d5kW#HVEYe!i+{@ zU1CyWbpVJ2qLU-xpd;~M&^~7uCubL;^Bw}hg+RFDIGy%4L1Gd!{uJl`3%ZgcpXvm` z+@KRkKy*5koSJkhJ|PxDILWb4d@`c5XO}4!wi>2Z@>*FWGr8353`jrPVEne8_7 zxnzzugUEcRE+%?+LlD$IEPvcR&~4R??dMZvNB4rc?WV|r`++Mu3*b#TMy_*@%KRS| CMgHUf diff --git a/public/favicons/mstile-150x150.png b/public/favicons/mstile-150x150.png deleted file mode 100644 index c3e853c930b56165b679f54025450e40bd998fcc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1751 zcmZ`(X;72r7XAQlLxsc}&_X{`FEqUxuS$b{8IxQ!N(g}fB7wvjXcbCn z*d!vzg&I@>EhC^JwYC*>5Ca4xVRb2s%1#U+LI_*f8h`Z1{o$E8=gjlWdCr+LXWlo5 zL8rjCgWCZBfO}HOOaL%JymxamBjcO+afvZ)i*cp70zmyGi*?pNjM$D%Wzqm3buR#< zX99r1NTsU);4BsZ)DZwcECm1?URi^mld+MA;p6XaEZF+nRFl(M&8%ul6+#IL^A4SP zJ9F%SbFfF?Dc_U&1%09DGTq6?U@-W*F|QSsC7g^mtQz7&V;A*{%S+2o9yZrk-<3DF z$(!ZAPP9O>e}8v>bHiiOm#&l}?n=4hZTW*fd_sqnU)SD<(bQ|}y2Y)H&0&tX6(DyX z;uuugK4tIL=H@GILDxRk>ZFEwoY8QvA;=>jJ}mC~m1}}%{++5jWUSi|E3X|+*U4XW zb#y&`&{QL>mRtDDHTAq1esiPv`sU^)i*f2@|I1!QFBRv})7ecUde3R+ewO@{arV31 z3pv9v1uH8nsR=1(V+3WFB^tFRlF9NRcy&MRIzQT~zh@8;L%^iOx4n19kI-|ijh7jgWcOT~}U zc1v2QSBSD*sr=$(7lyT<7~EW2pSjtjYkju4zM-4f<(|)8TU(<*?s;js3%Z3*uoR*3 z5@rG>{RA*3FLE)hG(wX|ZwlFD%kjf#sEcsXB z4u)I}7eBece#q%O5r-L>tG2%(s}%_mO<*6vDc*c~?zX)|)+pj4w!lJyDc5|;Txwr} z&K3oWu^^LR8f!jj{Q6J^FS+tX`K1Q-S}s9!2<f1B3L{#l(>>64GV6h2?wxIE!8)aYwL835Zf zb-q1!zoCxZJT5CW^8^ETxT5aE#=)#YoMMy=mt@(Ar@SB^?_Wf%Bm{-#4&KK7&|HOf z%nu7~6pAZ9$!90Q`NPR)Cg^2X((21Wc#9XgCSVN`rS8_v(y=w(&E2 z3ObQw(m{$Xyc+c#l$o5_SI~ju?!*ft3xNXUJZdmNw2dPQ}qZ*HZ<>QQ!N7(-JKX~T<9>5d!VW-3&Aris1;o@%A^K5M^Zcw`~ zz7#e_0QU?+dz|l(EAP{tC|lNf9{OLc;QhBp8qrgJKOvg}HDLGu4vb)yFfX#N?~B{H zw0r!K@W&NoA%5>SEl@>J-Fa^N7)B_#VhMjZUvAv5=7Qu@Z)5X*(MPXC&rNY+spHvd z*t>64tN6*D(yTlY9uYcw!vk_jOX^{?BF}%evb14j9mHcyE@p~aDJ?-4i@p*Iz^@3* zILsuqR$7F=p4?tdSu9rrE+QZxNlvf=yS2>^74ThDM(LImOw>;Wv6 zh{ewQtHR~~1PO^zvC%0X7F=}$GmL_uRR3TBlXcFHmz)?Kdzxb>Na1npVtE2K00_&* zb(ZEyff&qF-%f?+Boi=0TR5;StkKrqMLW%`?a1knEXoXh&)=@|&u8r|iWXE0tTUZj a?&SceZIA+;8?M+m0`PRFlkd1iWc&qc$r={` diff --git a/public/favicons/mstile-310x150.png b/public/favicons/mstile-310x150.png deleted file mode 100644 index e95cb9d2913245b7ee5055220c113e5dceece7a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1996 zcmb_dZBSEZ7QTorDp*_4Ql%|eisE8IfY53NQD{PdkN{}}4B^vUAOw(xFbWa;80{)l z5Gct~q5_H-=!Oc$8Zat?8!!+AVgiC#`3wO91VSXx(3?7r(;x11X7~MZ-t(M$pL6Ft z=Y7vTA4I@z+^}r}000~Pe9=SzSOW(DlMmLJLXnauNj}iFHr@;G1pqhm%~xXHgRtFU zUm_j=GIs#L$uj_;he9Wn0FaIV097;qp#B8_)~VcvU=JwK_dx+94D`b4o248bS5HkV z$CQV#p%h&B^$?-y~?f5c7VKo5Kfn$*+T)70?b8)q-98>U0tK2av@-jm#B87$oq{W9~?iblKo zyI}y#djz06VW3{A?(XPXH5i^JT$JvNSsI-p9tdivZwU1{NT(!T{_zqsE{%Vkk4AX+ z$KM0T&w_ zePFj|MM-(91wP#WP)BP=$Cr^($C&x{XNKjK$s6}Ik7S0G-!*fZoUC)p%gb0KCig_n zyk`Dm1ojxz2~#GK@GUSTF7jM+6@n(QI4s&^bq#C~0%lAdvK4-&x$Su7bGPCTB}aUTpXlR@35@M)Td0yi%@6 zxOFDOt#jU`q@Byv9W5+jjkO2hO`!bmSQpFwL5rBE-&sKMwX?QtJ-e2%{nT66Yw)fj zPy$v^FR+@=S||S~`LeC1l3$-$fJ2rDMzmjW5*YM06$ai#RTTE*QYt1;6IyGvwY8PjH7Zw&80pqMM@E97^ zvKabkO!(E5|zoxAQjFSk$8?%cEa1-z;PxuS>@$Oz z7I1rabIKFiLD1QW&hw=I3}%SHw(%(By)%>wnsjs}(kGF3Z>2h)JYq?}!6l-pY+)IuEcFT>#VT=>~(;&gZXrgw~! z{}M*HYn>TGeKvt9iO?SmaA0D>nA8|1h&s#wp$%|FxFTVQuVJoVlU(+qkb6;XE=~vp z3W2~U@N)h_NIpWP#bvyk;Nkw!R}djIlN81z#vHXvWgLm4C4qL#j8xE$mdZQ~0LQq) z8jE$`g*ZAs4wSU}jS>M6Nv%w6}cPVkSB1 aTjmc3RMsCcHQw&U##;R_1T^0}`t%>2oU%p$ diff --git a/public/favicons/mstile-310x310.png b/public/favicons/mstile-310x310.png deleted file mode 100644 index 7df73f26feb634e9d7f37744de3a8eeb042c255f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3512 zcmd5;X;f3!8of%b3R2dqR;?oys8~&iI8YG;5rh~-L_i1;L=4EFXbAHpwogQy5X>!# zfF_wX*Ixdw<_P=j7Y@ zPLdoQY_&DlX#xPCjkU9O0)WM6&W;U^K5_7P$GZ-d zO2z%PZgytY(cHn~h&%N`&dr46;k(6Sxz$7$pBAXOPRo9xxLl2$rSuY0@Y)XY0Uw`WrA5<9NWvG;LV%E=i?QH}5hZ8)W9 zg44X9n777QxgB;b%`3TdCU{ahIW;*Ib}p1z!X)54y4$-aCnjyB%QIkGXpo&8P5`gd zB(K+e1y2{9!P#0b`m`9;4^Nhou}5u|jxJrla_6S+>eucA08I?m`k-?}x1>+TB)EKA z=RNUD#5Kcnj?OuTKWHXt^Di4-*S&tERPW4ptJZ&cW#jhir;9taW<3|Ijh20FIK95NOX??y9X~}M-Vm|^UhJCF zH5vTbE#OQ2fNc^Rbb>$MsSA!=nMW;I!}{W>6Yi7|X}SGVN}1=-*M{jWmsC%~%stU7 zO&;SF3-Ya8Vz=fnJv&pB1P^(&o0~7GHf(Jm@(yP<-HK#uDHm zjX{yHyS@HDp|lQCx5&?I?1o?FHjv>+fI=S459mD#rx4mL&!d{-Up=nNh`mL4T3k*s zPqYY-YP|;IT9dt|cp=Tv>4d|()A2k{&xPx;BLeA_lb(iPtNk-d0eF(5P$m*Su4COG zS~2uFm0^N8or(c7){V1A7(4nQy#V(zxTN_3tcdA4X>8wRJY@_icpFa!5=^rw)Tk6( z)>Dc(J#$(CeaSDghYO#^CrwuRalGwNxR0=LY*5j|2P8Lt3i!4k_Q(9$K$&I^ca8rGfbErNZ-)Q0(wT`=oXe z(GAJu3dIHvPnO&&Wj4hOGS9m}hmC?k=m%}Ca3ihPL$UCX?imhoh_5U9QJ_mhAj?-e zz#*pK`*)Gx8V^Cy-N@7{wc0 zpRfK8AJ^mu%yqK)f4j$PqB=+)w3#tViiSx8amN?|DrB0=1%fadp|-S^v7u7cqLraq z&bo0XHn1yR&P+6li;rgQ@QGI2CMXq88HK$iae^k`zR|gtv0@yaG75w*hXw1Z!mA0c zLF*CUHCEovCT!Xm=msrx$pmb1D#<->h9-Pj>5=$I54?x3z|S^wn1W|RWlm$RP{JJ3 zpvo1!eNP-J(=&_G924e-QZ*^x!_uvRbG;k4?@!uGFrME2SU7cVZ3U${-aB+_>s6!S zU|V!TN}#B!yarn??B~f$>WS1Tq4|rzBs|-wm;^VPVlIO8vB7(%zMIDw|^(Ff-^jWlY-#d}*@C&P6jcfl5JAbJ{w1d7HhPZLkF zR1(>WD8$$hG0bQ>P{a-{_)UME8{)SRQ57rD5!J{1{yAc!-Qe5kt}@Dak08ArvDg4% z?-+3m&mOM`x2LUU>0ccok&Tl1yih@p$>UTzbh-g)Um5r&K*W|xAG9DD#w@Z$=bkLe z(daxH>^v$-G+s5;(ij)f{{GnheDGJqUTARKmZ_8{q@0SL39Wy3Ym{0BYf~DjW8<6= zMW*s2|Kka)#r{gLj7DJPP@0HYnO@{vikGqsiOYv26>Y_vuL(`6ImP8L(m)ci=i_Aa zA)hAdEZ!Gen}ouo$5*pDFf@DR@`8 z4%w9m)uX0^nZow+eu2Qo(cos;CzxS^BEm3qLU-UiBETed(En$sgC6j ztx5IpfVoYAA|>7Mf|i>c^GEuNlCW@~5MFYv1sHEH(!Y!IRT9`e&&m;nJCMa6gX*XM zLWrLpsWo{jzxFmrzBPql{0)n|G~B@#mdnux#|Mh?euLNG50$wa*}$#hcpB8oac+Z~ zgA3Yr*2xw28F#}|yD-}^ z7*h;pZ1a-?|CVq*_^iKg_&F-4%fX%3ikC6BI=SOFA{bAFOq!# zAR^<#)QV-7Tn!ByjzNuBp%b8?r-k;>TB)}Zm%2)0rLOhm-LKDT=+T{Zp-w)xrm<#2 g%~I&HUDgpaAYSti@|4w{d&p6-HV)QBR;RE04vf;u_5c6? diff --git a/public/favicons/mstile-70x70.png b/public/favicons/mstile-70x70.png deleted file mode 100644 index 1ab12d5449f5fce0d84fbb9b948ebc6954cbaa25..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1379 zcmZ{iYfRH;7{%XGpbSuyONh771t)BX6oz4-l!C1V8I-%|CQu6^D$-)HTx|P?auJJ& zLj@EEiW9^Mf)^B}-~d5x2I$Joa1o@XKoKY{wEdUWZ2PbeJIV8$oaFrSByZkqKVRYo z{jK@{fDK-r_yCPVUq%n9+0yZ=YZ}vzcK2}ypyrB!imao_Xo_cm4*wW6dVGbux@R?7xIc5Vr21^9kfnrd10xS~2Ln38ff z`EqK`5zo*MgCjD*M2C6sTjW8>^LH%`%}a|*;yd-zQ`7FYZXtwV;gs+O_j*=x#>ER+ zdFi>F^Qq|!P7AN)S=G~|(~0bOR#r-8T0$z5dZ8${a85k8HYpb0ebwF8)lk?}2}iKGYk27;OXQ=5#;G!b#! zn}|oOYuS!!0*dbCLqLg8+f3|tylC>`0HAfx3-2D3I6OZT6UfJH%A%oXhpoAH{c#8q zegGNLYGAgYqHgK zT5bJyN8Vgqt)vWO!{y!NAt1-q~5@$gZ34%fwgZmpPAeSofR0qCS00I=A?;Ew@^FYuO3| zuTZ3u@dA&#-~2QqC)4&$E)52 z)!Iwgsb@d;5doeFaDoD4I@2CET%gs${2Dh}fB?+Rptk`002e(RIMLPweA!aPl9!Xm zPN?4~?qIpkUMdhM;##dnGZ7yYPpK&FcFCB}YxbzOJX=BmMqR8~@`Y7@^7^8QVJY@n zjT)VJlwTfQkrF|OkaC1;a<-%0jR+_5ZjACxCttx;_E5 zca(WX7hC`wqCdh}(`}?;tcu$y6Rujl;x#Vh+A2rEb7nZ05Rr z2(vJXkWGNI78@euZve}}K(Db7t{yw1*41C_S)d>|A7CPq^?1NYS2ZQCf!^Akw@}&7 zH9Q&#WA8^BQx%_yG-8u@a(&C6?2&M`9gtY#5bMa&u~|b?B>f+C{OT6IQ=47Jiw)C! z;cw`KPe4#KR|3;WXy@A z{|B0>;qNuT;pCuDdH|V$rpCveh&dC5rYBLO&@ogx1%Slj$t6QQT8OoE2dT5m>r((g zS{m%37?@a^c;}lUP0)DAu{jcH`6LM4ImmBs>1x^Dg6f1kOAqY - - - -Created by potrace 1.14, written by Peter Selinger 2001-2017 - - - - - - - - diff --git a/public/favicons/site.webmanifest b/public/favicons/site.webmanifest deleted file mode 100644 index 32e00d4..0000000 --- a/public/favicons/site.webmanifest +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "", - "short_name": "", - "icons": [ - { - "src": "/favicons/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/favicons/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "theme_color": "#ffffff", - "background_color": "#ffffff", - "display": "standalone" -} diff --git a/tools/favicon-generator/favicon-generator.ts b/tools/favicon-generator/favicon-generator.ts new file mode 100644 index 0000000..0b717ac --- /dev/null +++ b/tools/favicon-generator/favicon-generator.ts @@ -0,0 +1,50 @@ +import fs from "node:fs/promises" + +import icoEndec from "ico-endec" +import sharp from "sharp" + +const ICO_SIZE = 32; +const APPLE_SIZE = 180; +const WEB_MANIFEST_192_SIZE = 192; +const WEB_MANIFEST_512_SIZE = 512; + +const pngSettings: sharp.PngOptions = { compressionLevel: 9, progressive: true, quality: 100 } + +const INPUT_SVG = "app/components/favicon/icon.svg"; +const OUTPUT_ICO = "app/components/favicon/favicon.ico"; +const OUTPUT_DEFAULT_ICO = "public/favicon.ico"; +const APPLE_TOUCH_ICON = "app/components/favicon/apple-touch-icon.png"; +const WEB_MANIFEST_192 = "app/components/favicon/icon-192.png"; +const WEB_MANIFEST_512 = "app/components/favicon/icon-512.png"; + +async function faviconIcoGenerator(svgImage: sharp.Sharp) { + const pngBuffer = await svgImage. + resize(ICO_SIZE, ICO_SIZE, { fit: "contain" }). + png({ compressionLevel: 0 }). + toBuffer() + + const icoBuffer = icoEndec.encode([pngBuffer]) + + await fs.writeFile(OUTPUT_ICO, icoBuffer); + await fs.writeFile(OUTPUT_DEFAULT_ICO, icoBuffer); +} + +async function faviconPngGenerator(svgImage: sharp.Sharp, filename: string, size: number) { + const pngBuffer = await svgImage. + resize(size, size, { fit: "contain" }). + png(pngSettings). + toBuffer() + + await fs.writeFile(filename, pngBuffer); +} + +async function run() { + const iconSvg = sharp(INPUT_SVG) + + await faviconIcoGenerator(iconSvg.clone()); + await faviconPngGenerator(iconSvg.clone(), APPLE_TOUCH_ICON, APPLE_SIZE); + await faviconPngGenerator(iconSvg.clone(), WEB_MANIFEST_192, WEB_MANIFEST_192_SIZE); + await faviconPngGenerator(iconSvg, WEB_MANIFEST_512, WEB_MANIFEST_512_SIZE); +} + +await run(); \ No newline at end of file diff --git a/tools/favicon-generator/ico-endec.d.ts b/tools/favicon-generator/ico-endec.d.ts new file mode 100644 index 0000000..31de9c4 --- /dev/null +++ b/tools/favicon-generator/ico-endec.d.ts @@ -0,0 +1,18 @@ +declare module 'ico-endec' { + export interface IconEntry { + width: number + height: number + colors: number + colorPlanes: number + bitsPerPixel: number + horizontalHotspot: number + verticalHotspot: number + imageSize: number + imageOffset: number + imageType: "png" | "bmp" + imageData: Uint8Array + } + + export function encode(images: Uint8Array[]): Uint8Array; + export function decode(buffer: Uint8Array): IconEntry[]; +}; \ No newline at end of file diff --git a/tools/favicon-generator/tsconfig.json b/tools/favicon-generator/tsconfig.json new file mode 100644 index 0000000..7dbc5a1 --- /dev/null +++ b/tools/favicon-generator/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json" +} \ No newline at end of file From 3f21814416e3df6a10defbdf3078e6250ddf3c92 Mon Sep 17 00:00:00 2001 From: Sebastian Fastner Date: Mon, 29 Jul 2024 14:57:41 +0200 Subject: [PATCH 2/4] fix: format --- app/components/favicon/FavIcon.tsx | 15 ++-- app/routes/[manifest.webmanifest].tsx | 18 ++--- package.json | 2 +- tools/favicon-generator/favicon-generator.ts | 72 ++++++++++++-------- tools/favicon-generator/ico-endec.d.ts | 8 +-- tools/favicon-generator/tsconfig.json | 2 +- 6 files changed, 65 insertions(+), 52 deletions(-) diff --git a/app/components/favicon/FavIcon.tsx b/app/components/favicon/FavIcon.tsx index 806ca1d..ac87658 100644 --- a/app/components/favicon/FavIcon.tsx +++ b/app/components/favicon/FavIcon.tsx @@ -7,12 +7,13 @@ import icon192 from "./icon-192.png" import icon512 from "./icon-512.png" export function FavIcon() { - return (<> - - - - - + return ( + <> + + + + + ) } @@ -21,4 +22,4 @@ export function webmanifestIcons() { icon192, icon512 } -} \ No newline at end of file +} diff --git a/app/routes/[manifest.webmanifest].tsx b/app/routes/[manifest.webmanifest].tsx index 65336d4..6954128 100644 --- a/app/routes/[manifest.webmanifest].tsx +++ b/app/routes/[manifest.webmanifest].tsx @@ -1,22 +1,22 @@ // Create webmanifest file with processed icons -import { webmanifestIcons } from "~/components/favicon/FavIcon"; +import { webmanifestIcons } from "~/components/favicon/FavIcon" export const loader = () => { - const icons = webmanifestIcons(); + const icons = webmanifestIcons() // handle "GET" request // set up our text content that will be returned in the response const webmanifest = JSON.stringify({ - "icons": [ - { "src": icons.icon192, "type": "image/png", "sizes": "192x192" }, - { "src": icons.icon512, "type": "image/png", "sizes": "512x512" } + icons: [ + { src: icons.icon192, type: "image/png", sizes: "192x192" }, + { src: icons.icon512, type: "image/png", sizes: "512x512" } ] }) - // return the text content, a status 200 success response, and set the content type to text/plain + // return the text content, a status 200 success response, and set the content type to text/plain return new Response(webmanifest, { status: 200, headers: { - "Content-Type": "application/json", + "Content-Type": "application/json" } - }); -}; \ No newline at end of file + }) +} diff --git a/package.json b/package.json index 23d60e0..87d09ad 100644 --- a/package.json +++ b/package.json @@ -59,4 +59,4 @@ "engines": { "node": ">=18.0.0" } -} \ No newline at end of file +} diff --git a/tools/favicon-generator/favicon-generator.ts b/tools/favicon-generator/favicon-generator.ts index 0b717ac..4d91bb4 100644 --- a/tools/favicon-generator/favicon-generator.ts +++ b/tools/favicon-generator/favicon-generator.ts @@ -3,48 +3,60 @@ import fs from "node:fs/promises" import icoEndec from "ico-endec" import sharp from "sharp" -const ICO_SIZE = 32; -const APPLE_SIZE = 180; -const WEB_MANIFEST_192_SIZE = 192; -const WEB_MANIFEST_512_SIZE = 512; - -const pngSettings: sharp.PngOptions = { compressionLevel: 9, progressive: true, quality: 100 } +const ICO_SIZE = 32 +const APPLE_SIZE = 180 +const WEB_MANIFEST_192_SIZE = 192 +const WEB_MANIFEST_512_SIZE = 512 + +const pngSettings: sharp.PngOptions = { + compressionLevel: 9, + progressive: true, + quality: 100 +} -const INPUT_SVG = "app/components/favicon/icon.svg"; -const OUTPUT_ICO = "app/components/favicon/favicon.ico"; -const OUTPUT_DEFAULT_ICO = "public/favicon.ico"; -const APPLE_TOUCH_ICON = "app/components/favicon/apple-touch-icon.png"; -const WEB_MANIFEST_192 = "app/components/favicon/icon-192.png"; -const WEB_MANIFEST_512 = "app/components/favicon/icon-512.png"; +const INPUT_SVG = "app/components/favicon/icon.svg" +const OUTPUT_ICO = "app/components/favicon/favicon.ico" +const OUTPUT_DEFAULT_ICO = "public/favicon.ico" +const APPLE_TOUCH_ICON = "app/components/favicon/apple-touch-icon.png" +const WEB_MANIFEST_192 = "app/components/favicon/icon-192.png" +const WEB_MANIFEST_512 = "app/components/favicon/icon-512.png" async function faviconIcoGenerator(svgImage: sharp.Sharp) { - const pngBuffer = await svgImage. - resize(ICO_SIZE, ICO_SIZE, { fit: "contain" }). - png({ compressionLevel: 0 }). - toBuffer() + const pngBuffer = await svgImage + .resize(ICO_SIZE, ICO_SIZE, { fit: "contain" }) + .png({ compressionLevel: 0 }) + .toBuffer() const icoBuffer = icoEndec.encode([pngBuffer]) - await fs.writeFile(OUTPUT_ICO, icoBuffer); - await fs.writeFile(OUTPUT_DEFAULT_ICO, icoBuffer); + await fs.writeFile(OUTPUT_ICO, icoBuffer) + await fs.writeFile(OUTPUT_DEFAULT_ICO, icoBuffer) } -async function faviconPngGenerator(svgImage: sharp.Sharp, filename: string, size: number) { - const pngBuffer = await svgImage. - resize(size, size, { fit: "contain" }). - png(pngSettings). - toBuffer() - - await fs.writeFile(filename, pngBuffer); +async function faviconPngGenerator( + svgImage: sharp.Sharp, + filename: string, + size: number +) { + const pngBuffer = await svgImage + .resize(size, size, { fit: "contain" }) + .png(pngSettings) + .toBuffer() + + await fs.writeFile(filename, pngBuffer) } async function run() { const iconSvg = sharp(INPUT_SVG) - await faviconIcoGenerator(iconSvg.clone()); - await faviconPngGenerator(iconSvg.clone(), APPLE_TOUCH_ICON, APPLE_SIZE); - await faviconPngGenerator(iconSvg.clone(), WEB_MANIFEST_192, WEB_MANIFEST_192_SIZE); - await faviconPngGenerator(iconSvg, WEB_MANIFEST_512, WEB_MANIFEST_512_SIZE); + await faviconIcoGenerator(iconSvg.clone()) + await faviconPngGenerator(iconSvg.clone(), APPLE_TOUCH_ICON, APPLE_SIZE) + await faviconPngGenerator( + iconSvg.clone(), + WEB_MANIFEST_192, + WEB_MANIFEST_192_SIZE + ) + await faviconPngGenerator(iconSvg, WEB_MANIFEST_512, WEB_MANIFEST_512_SIZE) } -await run(); \ No newline at end of file +await run() diff --git a/tools/favicon-generator/ico-endec.d.ts b/tools/favicon-generator/ico-endec.d.ts index 31de9c4..eee5e25 100644 --- a/tools/favicon-generator/ico-endec.d.ts +++ b/tools/favicon-generator/ico-endec.d.ts @@ -1,4 +1,4 @@ -declare module 'ico-endec' { +declare module "ico-endec" { export interface IconEntry { width: number height: number @@ -13,6 +13,6 @@ declare module 'ico-endec' { imageData: Uint8Array } - export function encode(images: Uint8Array[]): Uint8Array; - export function decode(buffer: Uint8Array): IconEntry[]; -}; \ No newline at end of file + export function encode(images: Uint8Array[]): Uint8Array + export function decode(buffer: Uint8Array): IconEntry[] +} diff --git a/tools/favicon-generator/tsconfig.json b/tools/favicon-generator/tsconfig.json index 7dbc5a1..b994545 100644 --- a/tools/favicon-generator/tsconfig.json +++ b/tools/favicon-generator/tsconfig.json @@ -1,3 +1,3 @@ { "extends": "@tsconfig/node20/tsconfig.json" -} \ No newline at end of file +} From eb16526f5873227fbf947f4d852d3326cdbf26fb Mon Sep 17 00:00:00 2001 From: Sebastian Fastner Date: Mon, 29 Jul 2024 15:02:31 +0200 Subject: [PATCH 3/4] fix: create icons on prepare event in package.json --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 87d09ad..1935b89 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "update:latest": "ncu --deep --upgrade --interactive", "update:minor": "ncu --deep --upgrade --interactive --target minor", "update:pnpm": "corepack up", - "deploy:prod": "sst deploy --stage production" + "deploy:prod": "sst deploy --stage production", + "prepare": "pnpm create:favicons" }, "dependencies": { "@effective/shadow": "^1.0.1", @@ -59,4 +60,4 @@ "engines": { "node": ">=18.0.0" } -} +} \ No newline at end of file From 0204e29b45e989a729bcf3d0c4e4e981d2481763 Mon Sep 17 00:00:00 2001 From: Sebastian Fastner Date: Mon, 29 Jul 2024 15:08:08 +0200 Subject: [PATCH 4/4] fix: formatting --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1935b89..e5421e7 100644 --- a/package.json +++ b/package.json @@ -60,4 +60,4 @@ "engines": { "node": ">=18.0.0" } -} \ No newline at end of file +}