mirror of
https://github.com/kremalicious/portfolio.git
synced 2024-12-23 01:29:41 +01:00
95 lines
2.8 KiB
TypeScript
95 lines
2.8 KiB
TypeScript
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
import sharp from 'sharp'
|
|
import ico from 'sharp-ico'
|
|
|
|
const imagesSourcePath = path.resolve(path.join(process.cwd(), 'src', 'images'))
|
|
const faviconSource = `${imagesSourcePath}/favicon-512.png`
|
|
const faviconSourceSvg = `${imagesSourcePath}/favicon.svg`
|
|
|
|
const outputWebRoot = path.resolve(path.join(process.cwd(), 'public'))
|
|
const outputManifest = path.resolve(
|
|
path.join(process.cwd(), 'public', 'manifest')
|
|
)
|
|
|
|
// All the sizes and meta we'll need
|
|
// https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs
|
|
const sizes = [32, 180, 192, 512]
|
|
const outputMeta = `
|
|
<link rel="icon" href="/favicon.ico" sizes="any" />
|
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
|
<link rel="manifest" href="/manifest/manifest.webmanifest" />
|
|
`
|
|
|
|
function createManifest(iconsizes: number[]) {
|
|
const manifest = {
|
|
name: 'matthias kretschmann',
|
|
short_name: 'mk',
|
|
display: 'standalone',
|
|
start_url: '/',
|
|
icons: iconsizes.map((size) => ({
|
|
src: `/manifest/favicon-${size}.png`,
|
|
type: 'image/png',
|
|
sizes: `${size}x${size}`
|
|
}))
|
|
}
|
|
fs.writeFileSync(
|
|
`${outputManifest}/manifest.webmanifest`,
|
|
JSON.stringify(manifest)
|
|
)
|
|
}
|
|
|
|
function nuke() {
|
|
fs.rmSync(outputManifest, { recursive: true, force: true })
|
|
fs.rmSync(`${outputWebRoot}/apple-touch-icon.png`, { force: true })
|
|
fs.rmSync(`${outputWebRoot}/favicon.ico`, { force: true })
|
|
fs.rmSync(`${outputWebRoot}/favicon.svg`, { force: true })
|
|
fs.mkdirSync(outputManifest, { recursive: true })
|
|
}
|
|
|
|
async function buildFavicons() {
|
|
try {
|
|
// Nuke all & create output folder first
|
|
nuke()
|
|
|
|
// copy over the svg, as it's handcrafted
|
|
fs.copyFileSync(faviconSourceSvg, `${outputWebRoot}/favicon.svg`)
|
|
|
|
// generate all the rest
|
|
await Promise.all(
|
|
sizes.map(async (size) => {
|
|
let destination = `${outputManifest}/favicon-${size}.png`
|
|
if (size === 180) destination = `${outputWebRoot}/apple-touch-icon.png`
|
|
|
|
// 32px size only used for favicon.ico
|
|
if (size === 32) {
|
|
await ico.sharpsToIco(
|
|
[sharp(faviconSource)],
|
|
`${outputWebRoot}/favicon.ico`,
|
|
{ sizes: [32, 24, 16], resizeOptions: {} }
|
|
)
|
|
fs.rmSync(destination, { force: true })
|
|
} else {
|
|
await sharp(faviconSource).resize(size, size).toFile(destination)
|
|
}
|
|
})
|
|
)
|
|
|
|
// write out manifest
|
|
createManifest([192, 512])
|
|
|
|
console.log(`
|
|
-----------------------------
|
|
Favicon generation complete!
|
|
-----------------------------
|
|
Add this to src/components/Meta/Favicon.tsx:
|
|
${outputMeta}
|
|
`)
|
|
} catch (error: unknown) {
|
|
console.error((error as Error).message)
|
|
}
|
|
}
|
|
|
|
buildFavicons()
|