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: { vite: {
plugins: [visualizer()], 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", "astro-compress": "1.1.28",
"concurrently": "7.6.0", "concurrently": "7.6.0",
"date-fns": "2.29.3", "date-fns": "2.29.3",
"favicons": "7.0.2",
"iconify-icon-names": "1.1.0", "iconify-icon-names": "1.1.0",
"immer": "9.0.18", "immer": "9.0.18",
"locales-ts": "1.0.0", "locales-ts": "1.0.0",
@ -35,6 +36,7 @@
"puppeteer-report": "3.1.0", "puppeteer-report": "3.1.0",
"rollup-plugin-visualizer": "5.9.0", "rollup-plugin-visualizer": "5.9.0",
"tailwindcss": "3.2.4", "tailwindcss": "3.2.4",
"ts-node": "10.9.1",
"type-fest": "3.5.3", "type-fest": "3.5.3",
"typescript": "4.9.4" "typescript": "4.9.4"
}, },
@ -610,6 +612,28 @@
"partytown": "bin/partytown.cjs" "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": { "node_modules/@emmetio/abbreviation": {
"version": "2.2.3", "version": "2.2.3",
"resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.2.3.tgz", "resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.2.3.tgz",
@ -1109,6 +1133,30 @@
"node": ">=10.13.0" "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": { "node_modules/@types/acorn": {
"version": "4.0.6", "version": "4.0.6",
"resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz",
@ -2605,6 +2653,12 @@
"node": ">=14" "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": { "node_modules/cross-fetch": {
"version": "3.1.5", "version": "3.1.5",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
@ -3445,6 +3499,12 @@
"node": ">=6" "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": { "node_modules/escape-string-regexp": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@ -3634,6 +3694,20 @@
"reusify": "^1.0.4" "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": { "node_modules/fd-slicer": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
@ -4660,9 +4734,9 @@
"dev": true "dev": true
}, },
"node_modules/json5": { "node_modules/json5": {
"version": "2.2.1", "version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true, "dev": true,
"bin": { "bin": {
"json5": "lib/cli.js" "json5": "lib/cli.js"
@ -4864,6 +4938,12 @@
"sourcemap-codec": "^1.4.8" "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": { "node_modules/markdown-table": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.2.tgz", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.2.tgz",
@ -7511,6 +7591,12 @@
"suf-log": "^2.5.3" "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": { "node_modules/scheduler": {
"version": "0.23.0", "version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
@ -8238,6 +8324,73 @@
"url": "https://github.com/sponsors/wooorm" "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": { "node_modules/tsconfig-resolver": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/tsconfig-resolver/-/tsconfig-resolver-3.0.1.tgz", "resolved": "https://registry.npmjs.org/tsconfig-resolver/-/tsconfig-resolver-3.0.1.tgz",
@ -8613,6 +8766,12 @@
"node": ">=8" "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": { "node_modules/vfile": {
"version": "5.3.4", "version": "5.3.4",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.4.tgz", "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": { "node_modules/xtend": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@ -9447,6 +9628,15 @@
"fd-slicer": "~1.1.0" "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": { "node_modules/yocto-queue": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "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==", "integrity": "sha512-Zbr2Eo0AQ4yzmQr/36/h+6LKjmdVBB3Q5cGzO6rtlIKB/IOpbQVUZW+XAnhpJmJr9sIF97OZjgbhG9k7Sjn4yw==",
"dev": true "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": { "@emmetio/abbreviation": {
"version": "2.2.3", "version": "2.2.3",
"resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.2.3.tgz", "resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.2.3.tgz",
@ -10316,6 +10527,30 @@
"integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==",
"dev": true "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": { "@types/acorn": {
"version": "4.0.6", "version": "4.0.6",
"resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz",
@ -11473,6 +11708,12 @@
"path-type": "^4.0.0" "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": { "cross-fetch": {
"version": "3.1.5", "version": "3.1.5",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
@ -12002,6 +12243,12 @@
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true "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": { "escape-string-regexp": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@ -12142,6 +12389,17 @@
"reusify": "^1.0.4" "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": { "fd-slicer": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
@ -12872,9 +13130,9 @@
"dev": true "dev": true
}, },
"json5": { "json5": {
"version": "2.2.1", "version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true "dev": true
}, },
"jsonc-parser": { "jsonc-parser": {
@ -13028,6 +13286,12 @@
"sourcemap-codec": "^1.4.8" "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": { "markdown-table": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.2.tgz", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.2.tgz",
@ -14847,6 +15111,12 @@
"suf-log": "^2.5.3" "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": { "scheduler": {
"version": "0.23.0", "version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
@ -15379,6 +15649,47 @@
"integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==", "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==",
"dev": true "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": { "tsconfig-resolver": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/tsconfig-resolver/-/tsconfig-resolver-3.0.1.tgz", "resolved": "https://registry.npmjs.org/tsconfig-resolver/-/tsconfig-resolver-3.0.1.tgz",
@ -15632,6 +15943,12 @@
"sade": "^1.7.3" "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": { "vfile": {
"version": "5.3.4", "version": "5.3.4",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.4.tgz", "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.4.tgz",
@ -16051,6 +16368,22 @@
"dev": true, "dev": true,
"requires": {} "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": { "xtend": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@ -16140,6 +16473,12 @@
"fd-slicer": "~1.1.0" "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": { "yocto-queue": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",

View file

@ -13,9 +13,10 @@
"dev": "astro dev", "dev": "astro dev",
"build": "astro build", "build": "astro build",
"preview": "astro preview", "preview": "astro preview",
"generate-cv": "node scripts/generate-cv.cjs", "generate-cv": "ts-node scripts/generate-cv.ts",
"prettier:check": "prettier --check --ignore-path .gitignore .", "generate-favicons": "ts-node scripts/generate-favicons.ts",
"prettier:write": "prettier --write --ignore-path .gitignore .", "prettier:check": "prettier --check .",
"prettier:write": "prettier --write .",
"astro:check": "astro check", "astro:check": "astro check",
"ts:check": "tsc --jsx preserve --skipLibCheck", "ts:check": "tsc --jsx preserve --skipLibCheck",
"check": "concurrently npm:*:check" "check": "concurrently npm:*:check"
@ -36,6 +37,7 @@
"astro-compress": "1.1.28", "astro-compress": "1.1.28",
"concurrently": "7.6.0", "concurrently": "7.6.0",
"date-fns": "2.29.3", "date-fns": "2.29.3",
"favicons": "7.0.2",
"iconify-icon-names": "1.1.0", "iconify-icon-names": "1.1.0",
"immer": "9.0.18", "immer": "9.0.18",
"locales-ts": "1.0.0", "locales-ts": "1.0.0",
@ -48,6 +50,7 @@
"puppeteer-report": "3.1.0", "puppeteer-report": "3.1.0",
"rollup-plugin-visualizer": "5.9.0", "rollup-plugin-visualizer": "5.9.0",
"tailwindcss": "3.2.4", "tailwindcss": "3.2.4",
"ts-node": "10.9.1",
"type-fest": "3.5.3", "type-fest": "3.5.3",
"typescript": "4.9.4" "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 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'; import type { ReadonlyDeep } from 'type-fest';
const config = { const config = {
@ -14,7 +14,7 @@ const config = {
title: 'Mark Freeman - Senior React Developer', title: 'Mark Freeman - Senior React Developer',
description: 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.', '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: { pdf: {
footer: footer:

View file

@ -20,11 +20,11 @@ export interface MetaConfig {
description: string; 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. * Specified icon will be displayed next to the page title in browser tab.
*/ */
favicon: string; faviconPath: string;
/** /**
* [WEB] Title used in open graph links. * [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 type { Data } from '@/types/data';
import Analytics from '@/web/analytics/analytics.astro'; import Analytics from '@/web/analytics/analytics.astro';
import Head from './head.astro';
export interface Props extends Pick<Data['config'], 'meta' | 'i18n'> {} export interface Props extends Pick<Data['config'], 'meta' | 'i18n'> {}
@ -9,33 +10,7 @@ const { meta, i18n } = Astro.props;
<!DOCTYPE html> <!DOCTYPE html>
<html lang={i18n.locale.code} class="scroll-smooth"> <html lang={i18n.locale.code} class="scroll-smooth">
<head> <Head meta={meta} />
<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>
<body class="flex justify-center overflow-x-hidden bg-gray-50 dark:bg-gray-900 xl:relative xl:left-7"> <body class="flex justify-center overflow-x-hidden bg-gray-50 dark:bg-gray-900 xl:relative xl:left-7">
<Analytics /> <Analytics />
<slot /> <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/*"] "@/*": ["src/*"]
} }
}, },
"include": ["**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.astro"] "include": ["**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.astro"],
"ts-node": {
"transpileOnly": true,
"compilerOptions": {
"module": "CommonJS"
}
}
} }