Setup favicon generation (#178)

Co-authored-by: Konrad Szwarc <konrad.szwarc.dev@gmail.com>
This commit is contained in:
Szymon Kin 2023-01-26 21:19:05 +01:00 committed by GitHub
parent 2d09310352
commit b249607f77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 585 additions and 104 deletions

13
.prettierignore Normal file
View file

@ -0,0 +1,13 @@
# Dependencies
node_modules
# OS
.DS_Store
# Build output
dist
stats.html
# Favicon generation output
**/favicons/**
*.auto-generated*

View file

@ -15,5 +15,10 @@ export default defineConfig({
],
vite: {
plugins: [visualizer()],
resolve: {
alias: {
'date-fns/locale': 'date-fns/locale/index.js',
},
},
},
});

351
package-lock.json generated
View file

@ -23,6 +23,7 @@
"astro-compress": "1.1.28",
"concurrently": "7.6.0",
"date-fns": "2.29.3",
"favicons": "7.0.2",
"iconify-icon-names": "1.1.0",
"immer": "9.0.18",
"locales-ts": "1.0.0",
@ -35,6 +36,7 @@
"puppeteer-report": "3.1.0",
"rollup-plugin-visualizer": "5.9.0",
"tailwindcss": "3.2.4",
"ts-node": "10.9.1",
"type-fest": "3.5.3",
"typescript": "4.9.4"
},
@ -610,6 +612,28 @@
"partytown": "bin/partytown.cjs"
}
},
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@emmetio/abbreviation": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.2.3.tgz",
@ -1109,6 +1133,30 @@
"node": ">=10.13.0"
}
},
"node_modules/@tsconfig/node10": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
"integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
"dev": true
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true
},
"node_modules/@tsconfig/node16": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
"integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
"dev": true
},
"node_modules/@types/acorn": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz",
@ -2605,6 +2653,12 @@
"node": ">=14"
}
},
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"node_modules/cross-fetch": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
@ -3445,6 +3499,12 @@
"node": ">=6"
}
},
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"dev": true
},
"node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@ -3634,6 +3694,20 @@
"reusify": "^1.0.4"
}
},
"node_modules/favicons": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/favicons/-/favicons-7.0.2.tgz",
"integrity": "sha512-M/qE3ERHOBu0+Op+61jx8CdvOnSKrrl2zxUPpoGgsNyfjuGqRsK80zYoA5Uwdxl8QM4egfhBWZp1j7KK3YnOMg==",
"dev": true,
"dependencies": {
"escape-html": "^1.0.3",
"sharp": "^0.31.1",
"xml2js": "^0.4.23"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
@ -4660,9 +4734,9 @@
"dev": true
},
"node_modules/json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"bin": {
"json5": "lib/cli.js"
@ -4864,6 +4938,12 @@
"sourcemap-codec": "^1.4.8"
}
},
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"node_modules/markdown-table": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.2.tgz",
@ -7511,6 +7591,12 @@
"suf-log": "^2.5.3"
}
},
"node_modules/sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
"dev": true
},
"node_modules/scheduler": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
@ -8238,6 +8324,73 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/ts-node": {
"version": "10.9.1",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
"integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
"dev": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
"@tsconfig/node16": "^1.0.2",
"acorn": "^8.4.1",
"acorn-walk": "^8.1.1",
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"v8-compile-cache-lib": "^3.0.1",
"yn": "3.1.1"
},
"bin": {
"ts-node": "dist/bin.js",
"ts-node-cwd": "dist/bin-cwd.js",
"ts-node-esm": "dist/bin-esm.js",
"ts-node-script": "dist/bin-script.js",
"ts-node-transpile-only": "dist/bin-transpile.js",
"ts-script": "dist/bin-script-deprecated.js"
},
"peerDependencies": {
"@swc/core": ">=1.2.50",
"@swc/wasm": ">=1.2.50",
"@types/node": "*",
"typescript": ">=2.7"
},
"peerDependenciesMeta": {
"@swc/core": {
"optional": true
},
"@swc/wasm": {
"optional": true
}
}
},
"node_modules/ts-node/node_modules/acorn-walk": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
"integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
"dev": true,
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/ts-node/node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
},
"node_modules/ts-node/node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true,
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/tsconfig-resolver": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/tsconfig-resolver/-/tsconfig-resolver-3.0.1.tgz",
@ -8613,6 +8766,12 @@
"node": ">=8"
}
},
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
},
"node_modules/vfile": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.4.tgz",
@ -9336,6 +9495,28 @@
}
}
},
"node_modules/xml2js": {
"version": "0.4.23",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
"integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
"dev": true,
"dependencies": {
"sax": ">=0.6.0",
"xmlbuilder": "~11.0.0"
},
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/xmlbuilder": {
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
"dev": true,
"engines": {
"node": ">=4.0"
}
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@ -9447,6 +9628,15 @@
"fd-slicer": "~1.1.0"
}
},
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
@ -9918,6 +10108,27 @@
"integrity": "sha512-Zbr2Eo0AQ4yzmQr/36/h+6LKjmdVBB3Q5cGzO6rtlIKB/IOpbQVUZW+XAnhpJmJr9sIF97OZjgbhG9k7Sjn4yw==",
"dev": true
},
"@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"requires": {
"@jridgewell/trace-mapping": "0.3.9"
},
"dependencies": {
"@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
"requires": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
}
}
},
"@emmetio/abbreviation": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.2.3.tgz",
@ -10316,6 +10527,30 @@
"integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==",
"dev": true
},
"@tsconfig/node10": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
"integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
"dev": true
},
"@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true
},
"@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true
},
"@tsconfig/node16": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
"integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
"dev": true
},
"@types/acorn": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz",
@ -11473,6 +11708,12 @@
"path-type": "^4.0.0"
}
},
"create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"cross-fetch": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
@ -12002,6 +12243,12 @@
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"dev": true
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@ -12142,6 +12389,17 @@
"reusify": "^1.0.4"
}
},
"favicons": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/favicons/-/favicons-7.0.2.tgz",
"integrity": "sha512-M/qE3ERHOBu0+Op+61jx8CdvOnSKrrl2zxUPpoGgsNyfjuGqRsK80zYoA5Uwdxl8QM4egfhBWZp1j7KK3YnOMg==",
"dev": true,
"requires": {
"escape-html": "^1.0.3",
"sharp": "^0.31.1",
"xml2js": "^0.4.23"
}
},
"fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
@ -12872,9 +13130,9 @@
"dev": true
},
"json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true
},
"jsonc-parser": {
@ -13028,6 +13286,12 @@
"sourcemap-codec": "^1.4.8"
}
},
"make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"markdown-table": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.2.tgz",
@ -14847,6 +15111,12 @@
"suf-log": "^2.5.3"
}
},
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
"dev": true
},
"scheduler": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
@ -15379,6 +15649,47 @@
"integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==",
"dev": true
},
"ts-node": {
"version": "10.9.1",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
"integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
"dev": true,
"requires": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
"@tsconfig/node16": "^1.0.2",
"acorn": "^8.4.1",
"acorn-walk": "^8.1.1",
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"v8-compile-cache-lib": "^3.0.1",
"yn": "3.1.1"
},
"dependencies": {
"acorn-walk": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
"integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
"dev": true
},
"arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
},
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true
}
}
},
"tsconfig-resolver": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/tsconfig-resolver/-/tsconfig-resolver-3.0.1.tgz",
@ -15632,6 +15943,12 @@
"sade": "^1.7.3"
}
},
"v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
},
"vfile": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.4.tgz",
@ -16051,6 +16368,22 @@
"dev": true,
"requires": {}
},
"xml2js": {
"version": "0.4.23",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
"integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
"dev": true,
"requires": {
"sax": ">=0.6.0",
"xmlbuilder": "~11.0.0"
}
},
"xmlbuilder": {
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
"dev": true
},
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@ -16140,6 +16473,12 @@
"fd-slicer": "~1.1.0"
}
},
"yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true
},
"yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",

View file

@ -13,9 +13,10 @@
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"generate-cv": "node scripts/generate-cv.cjs",
"prettier:check": "prettier --check --ignore-path .gitignore .",
"prettier:write": "prettier --write --ignore-path .gitignore .",
"generate-cv": "ts-node scripts/generate-cv.ts",
"generate-favicons": "ts-node scripts/generate-favicons.ts",
"prettier:check": "prettier --check .",
"prettier:write": "prettier --write .",
"astro:check": "astro check",
"ts:check": "tsc --jsx preserve --skipLibCheck",
"check": "concurrently npm:*:check"
@ -36,6 +37,7 @@
"astro-compress": "1.1.28",
"concurrently": "7.6.0",
"date-fns": "2.29.3",
"favicons": "7.0.2",
"iconify-icon-names": "1.1.0",
"immer": "9.0.18",
"locales-ts": "1.0.0",
@ -48,6 +50,7 @@
"puppeteer-report": "3.1.0",
"rollup-plugin-visualizer": "5.9.0",
"tailwindcss": "3.2.4",
"ts-node": "10.9.1",
"type-fest": "3.5.3",
"typescript": "4.9.4"
}

View file

@ -1,13 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 36 36">
<path fill="#000" d="M22.25 4h-8.5a1 1 0 0 0-.96.73l-5.54 19.4a.5.5 0 0 0 .62.62l5.05-1.44a2 2 0 0 0 1.38-1.4l3.22-11.66a.5.5 0 0 1 .96 0l3.22 11.67a2 2 0 0 0 1.38 1.39l5.05 1.44a.5.5 0 0 0 .62-.62l-5.54-19.4a1 1 0 0 0-.96-.73Z"/>
<path fill="url(#gradient)" d="M18 28a7.63 7.63 0 0 1-5-2c-1.4 2.1-.35 4.35.6 5.55.14.17.41.07.47-.15.44-1.8 2.93-1.22 2.93.6 0 2.28.87 3.4 1.72 3.81.34.16.59-.2.49-.56-.31-1.05-.29-2.46 1.29-3.25 3-1.5 3.17-4.83 2.5-6-.67.67-2.6 2-5 2Z"/>
<defs>
<linearGradient id="gradient" x1="16" x2="16" y1="32" y2="24" gradientUnits="userSpaceOnUse">
<stop stop-color="#000"/>
<stop offset="1" stop-color="#000" stop-opacity="0"/>
</linearGradient>
</defs>
<style>
@media (prefers-color-scheme:dark){:root{filter:invert(100%)}}
</style>
</svg>

Before

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 975 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
public/favicons/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View file

@ -0,0 +1,26 @@
{
"name": "Mark Freeman - Senior React Developer",
"short_name": "Mark Freeman - Senior React Developer",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sodales ac dui at vestibulum. In condimentum metus id dui tincidunt, in blandit mi vehicula.",
"dir": "auto",
"lang": "en-US",
"display": "standalone",
"orientation": "any",
"start_url": ".",
"background_color": "#fff",
"theme_color": "#fff",
"icons": [
{
"src": "/favicons/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/favicons/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
}
]
}

View file

@ -1,50 +0,0 @@
const { exec } = require('node:child_process');
const path = require('node:path');
const fs = require('node:fs');
const puppeteer = require('puppeteer');
const report = require('puppeteer-report');
const waitFor = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const retry = async ({ promise, retries, retryTime }) => {
try {
return await promise();
} catch (error) {
if (retries <= 0) throw error;
await waitFor(retryTime);
return await retry({ promise, retries: retries - 1, retryTime });
}
};
const config = {
path: path.join(__dirname, '..', 'public', 'cv.pdf'),
format: 'A4',
printBackground: true,
margin: { top: '10mm', right: '10mm', bottom: '10mm', left: '10mm' },
};
const main = async () => {
const child = exec('npm run dev');
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.setViewport({ width: 794, height: 1122, deviceScaleFactor: 2 });
await retry({
promise: () => page.goto('http://localhost:3000/pdf', { waitUntil: 'networkidle0' }),
retries: 5,
retryTime: 1000,
});
await report.pdfPage(page, config);
await browser.close();
child.kill();
};
main();

59
scripts/generate-cv.ts Normal file
View file

@ -0,0 +1,59 @@
import { exec } from 'node:child_process';
import * as path from 'node:path';
import * as puppeteer from 'puppeteer';
import { pdfPage } from 'puppeteer-report';
const waitFor = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
const goTo = async (page: puppeteer.Page, url: string) => {
await page.goto(url, { waitUntil: 'networkidle0' });
};
type GoToReturn = ReturnType<typeof goTo>;
interface RetryOptions {
promise: () => GoToReturn;
retries: number;
retryTime: number;
}
const retry = async ({ promise, retries, retryTime }: RetryOptions): GoToReturn => {
try {
return await promise();
} catch (error) {
if (retries <= 0) throw error;
await waitFor(retryTime);
return await retry({ promise, retries: retries - 1, retryTime });
}
};
const main = async () => {
const child = exec('npm run dev');
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.setViewport({ width: 794, height: 1122, deviceScaleFactor: 2 });
await retry({
promise: () => goTo(page, 'http://localhost:3000/pdf'),
retries: 5,
retryTime: 1000,
});
await pdfPage(page, {
path: path.join(__dirname, '..', 'public', 'cv.pdf'),
format: 'A4',
printBackground: true,
margin: { top: '10mm', right: '10mm', bottom: '10mm', left: '10mm' },
});
await browser.close();
child.kill();
};
main();

View file

@ -0,0 +1,53 @@
import { favicons, config as faviconsConfig, FaviconFile, FaviconImage } from 'favicons';
import config from '../src/data/config';
import { mkdir, writeFile, rm } from 'fs/promises';
import { existsSync } from 'fs';
const faviconsDirectory = './public/favicons';
const saveFile = async (file: FaviconFile | FaviconImage) => {
await writeFile(`${faviconsDirectory}/${file.name}`, file.contents);
console.log(`${file.name} has been created successfully`);
};
(async () => {
const { faviconPath } = config.meta;
const response = await favicons(`.${faviconPath}`, {
...faviconsConfig.defaults,
path: '/favicons',
appName: config.meta.title,
appDescription: config.meta.description,
appShortName: config.meta.title,
lang: config.i18n.locale.code,
start_url: '.',
icons: {
android: ['android-chrome-192x192.png', 'android-chrome-512x512.png'],
windows: false,
yandex: false,
appleStartup: false,
appleIcon: ['apple-touch-icon.png'],
favicons: ['favicon-16x16.png', 'favicon-32x32.png', 'favicon.ico'],
},
});
if (existsSync(faviconsDirectory)) {
await rm(faviconsDirectory, { recursive: true });
}
await mkdir(faviconsDirectory);
await Promise.all([...response.images, ...response.files].map(saveFile));
const comments = [
'<!-- This file is auto-generated. Do not edit it manually. -->\n',
'<!-- In order to apply changes to it, adjust configuration object in generate-favicons.ts script and run it -->\n',
];
const formattedHtml = response.html.map((line) => line.replace('>', '/>')).join('\n');
const pathToFaviconsFile = './src/web/head/favicons.auto-generated.astro';
await writeFile(pathToFaviconsFile, [...comments, formattedHtml, '\n']);
console.log(`${pathToFaviconsFile} has been updated successfully`);
})();

View file

@ -1,5 +1,5 @@
import type { Config } from '@/types/data';
import enUS from 'date-fns/locale/en-US/index.js';
import { enUS } from 'date-fns/locale';
import type { ReadonlyDeep } from 'type-fest';
const config = {
@ -14,7 +14,7 @@ const config = {
title: 'Mark Freeman - Senior React Developer',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sodales ac dui at vestibulum. In condimentum metus id dui tincidunt, in blandit mi vehicula.',
favicon: '/favicon.svg',
faviconPath: '/src/assets/my-image.jpeg',
},
pdf: {
footer:

View file

@ -20,11 +20,11 @@ export interface MetaConfig {
description: string;
/**
* [WEB] URL or path to the page's favicon.
* [WEB] Absolute path to the image used for favicons generation.
*
* Specified icon will be displayed next to the page title in browser tab.
*/
favicon: string;
faviconPath: string;
/**
* [WEB] Title used in open graph links.

View file

@ -0,0 +1,19 @@
---
import Favicons from '@/web/head/favicons.auto-generated.astro';
import InitialTheme from '@/web/head/initial-theme.astro';
import Meta from '@/web/head/meta.astro';
import type { MetaConfig } from '@/types/config/meta-config.types';
interface Props {
meta: MetaConfig;
}
const { meta } = Astro.props;
---
<head>
<Meta meta={meta} />
<Favicons />
<InitialTheme />
</head>

View file

@ -1,6 +1,7 @@
---
import type { Data } from '@/types/data';
import Analytics from '@/web/analytics/analytics.astro';
import Head from './head.astro';
export interface Props extends Pick<Data['config'], 'meta' | 'i18n'> {}
@ -9,33 +10,7 @@ const { meta, i18n } = Astro.props;
<!DOCTYPE html>
<html lang={i18n.locale.code} class="scroll-smooth">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>{meta.title}</title>
<meta name="description" content={meta.description} />
<link rel="icon" type="image/svg+xml" href={meta.favicon} />
<meta property="og:title" content={meta.ogTitle ?? meta.title} />
<meta property="og:description" content={meta.ogDescription ?? meta.description} />
{meta.ogImage && <meta property="og:image" content={meta.ogImage} />}
<script is:inline>
const theme = (() => {
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme');
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
})();
if (theme === 'light') {
document.documentElement.classList.remove('dark');
} else {
document.documentElement.classList.add('dark');
}
window.localStorage.setItem('theme', theme);
</script>
</head>
<Head meta={meta} />
<body class="flex justify-center overflow-x-hidden bg-gray-50 dark:bg-gray-900 xl:relative xl:left-7">
<Analytics />
<slot />

View file

@ -0,0 +1,12 @@
<!-- This file is auto-generated. Do not edit it manually. -->
<!-- In order to apply changes to it, adjust configuration object in generate-favicons.ts script and run it -->
<link rel="icon" type="image/x-icon" href="/favicons/favicon.ico"/>
<link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png"/>
<link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png"/>
<link rel="manifest" href="/favicons/manifest.webmanifest"/>
<meta name="mobile-web-app-capable" content="yes"/>
<meta name="theme-color" content="#fff"/>
<meta name="application-name" content="Mark Freeman - Senior React Developer"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
<meta name="apple-mobile-web-app-title" content="Mark Freeman - Senior React Developer"/>

View file

@ -0,0 +1,16 @@
<script is:inline>
const theme = (() => {
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme');
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
})();
if (theme === 'light') {
document.documentElement.classList.remove('dark');
} else {
document.documentElement.classList.add('dark');
}
window.localStorage.setItem('theme', theme);
</script>

18
src/web/head/meta.astro Normal file
View file

@ -0,0 +1,18 @@
---
import type { MetaConfig } from '@/types/config/meta-config.types';
interface Props {
meta: MetaConfig;
}
const { meta } = Astro.props;
---
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>{meta.title}</title>
<meta name="description" content={meta.description} />
<meta property="og:title" content={meta.ogTitle ?? meta.title} />
<meta property="og:description" content={meta.ogDescription ?? meta.description} />
{meta.ogImage && <meta property="og:image" content={meta.ogImage} />}

View file

@ -35,5 +35,11 @@
"@/*": ["src/*"]
}
},
"include": ["**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.astro"]
"include": ["**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.astro"],
"ts-node": {
"transpileOnly": true,
"compilerOptions": {
"module": "CommonJS"
}
}
}