-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
sharp.ts
81 lines (66 loc) · 2.33 KB
/
sharp.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import type { FormatEnum } from 'sharp';
import { AstroError, AstroErrorData } from '../../core/errors/index.js';
import type { ImageOutputFormat, ImageQualityPreset } from '../types.js';
import {
baseService,
parseQuality,
type BaseServiceTransform,
type LocalImageService,
} from './service.js';
let sharp: typeof import('sharp');
const qualityTable: Record<ImageQualityPreset, number> = {
low: 25,
mid: 50,
high: 80,
max: 100,
};
async function loadSharp() {
let sharpImport: typeof import('sharp');
try {
sharpImport = (await import('sharp')).default;
} catch (e) {
throw new AstroError(AstroErrorData.MissingSharp);
}
return sharpImport;
}
const sharpService: LocalImageService = {
validateOptions: baseService.validateOptions,
getURL: baseService.getURL,
parseURL: baseService.parseURL,
getHTMLAttributes: baseService.getHTMLAttributes,
getSrcSet: baseService.getSrcSet,
async transform(inputBuffer, transformOptions) {
if (!sharp) sharp = await loadSharp();
const transform: BaseServiceTransform = transformOptions as BaseServiceTransform;
// Return SVGs as-is
// TODO: Sharp has some support for SVGs, we could probably support this once Sharp is the default and only service.
if (transform.format === 'svg') return { data: inputBuffer, format: 'svg' };
let result = sharp(inputBuffer, { failOnError: false, pages: -1 });
// always call rotate to adjust for EXIF data orientation
result.rotate();
// Never resize using both width and height at the same time, prioritizing width.
if (transform.height && !transform.width) {
result.resize({ height: Math.round(transform.height) });
} else if (transform.width) {
result.resize({ width: Math.round(transform.width) });
}
if (transform.format) {
let quality: number | string | undefined = undefined;
if (transform.quality) {
const parsedQuality = parseQuality(transform.quality);
if (typeof parsedQuality === 'number') {
quality = parsedQuality;
} else {
quality = transform.quality in qualityTable ? qualityTable[transform.quality] : undefined;
}
}
result.toFormat(transform.format as keyof FormatEnum, { quality: quality });
}
const { data, info } = await result.toBuffer({ resolveWithObject: true });
return {
data: data,
format: info.format as ImageOutputFormat,
};
},
};
export default sharpService;