nextui/apps/docs/scripts/image-sharp.ts

72 lines
1.7 KiB
TypeScript

import fetch from 'node-fetch'
import sharp from 'sharp'
/**
* This module was inspired by Zach Leatherman's `avatar-local-cache` library.
* Check out https://github.com/zachleat/avatar-local-cache for a similar,
* pre-packaged solution.
*/
export interface AvatarCacheOptions {
/** The path to write the images to. */
outputDirectory: string
/** The max width of the avatars. */
width?: number
}
export class AvatarCache {
outputDirectory: string
width: number
constructor({ outputDirectory, width = 120 }: AvatarCacheOptions) {
this.outputDirectory = outputDirectory
this.width = width
}
async urlToFile(url: string, outputFileSlug: string) {
try {
const response = await fetch(url)
if (!response.ok) {
throw new Error(
`Bad status code for ${url}. ${response.status}: ${response.statusText}`,
)
}
const body = await response.arrayBuffer()
return this.processImage(body, outputFileSlug)
} catch (error) {
// eslint-disable-next-line no-console
console.error(`Error processing ${url}\nError: ${error}`)
}
}
private async processImage(body: ArrayBuffer, outputFileSlug: string) {
const { width, outputDirectory } = this
const output = `${outputDirectory}/${outputFileSlug}`
const img = sharp(Buffer.from(body)).resize({
width: width,
withoutEnlargement: true,
})
const metadata = await img.metadata()
await this.toJpeg(img, metadata, `${output}.jpg`)
return `${outputFileSlug}.jpg`
}
private async toJpeg(
img: sharp.Sharp,
metadata: sharp.Metadata,
slug: string,
) {
const jpeg = metadata.format !== 'jpeg' ? img.jpeg() : img
await jpeg.toFile(slug)
}
}
export default AvatarCache